Unity ----- 对象池GameObjectPool
孙广东 2014.6.28
非常早之前看到的外国文章,认为不错,分享一下。 对象池在AssetStore中也是有非常多插件的,可是有些重了。自己写一个轻量的岂不是非常好。
当你须要创建大量某种类型对象时,它能够方便地又一次使用单个对象,而不是不断地 创建/销毁(操作会导致大量的垃圾回收)。此ObjectPool脚本,生成和回收您的游戏对象的对象池。
代码:https://github.com/UnityPatterns/ObjectPool
http://unitypatterns.com/resource/objectpool/
特性:
?选择性地池对象基于prefab类型
?简单和表达式语法 对于 实例化和回收
?轻松地预先实例化对象,以防止执行时实例化
?搜索和跟踪全部生成/池子内的在场景中实例化的
怎么使用?
通常情况下,当您实例化并销毁prefabs的实例,您在执行时不断创建新的对象和摧毁它们。这可能会导致执行时垃圾回收和偶尔的帧速率下降。
ObjectPool 能够防止这样的。通过预先实例化。而不是被摧毁然后又一次生成对象!
生成池子中的对象:
比如,假设我有能发射子弹对象的炮塔。我能创建 10 枚一模一样的子弹对象并又一次使用。子弹将永远不会被销毁。仅仅是取消激活、须要生成时又一次激活他们。
ObjectPool要做到这一点,你仅仅要调用CreatePool() 生成指定Prefab的对象。
public class Turret : MonoBehaviour
{
public Bullet bulletPrefab;
void Start()
{
//Create a pool with 10 pre-instantiated bullets in it
bulletPrefab.CreatePool(10);
//Or you could also pre-instantiate none, and the system will instantiate them as it needs them
bulletPrefab.CreatePool();
}
}
如今你能够使用ObjectPool类中的Spawn() and Recycle() 来取代Instantiate() and Destroy()方法。比如。当抢发射子弹时。我生成子弹实例:
public class Turret : MonoBehaviour
{
public Bullet bulletPrefab;
public void ShootBullet()
{
//Spawn a bullet at my position with my rotation
bulletPrefab.Spawn(transform.position, transform.rotation);
}
}
当你想要回收这个实例,在你想要消失的组件或者对象上调用Recycle()函数。
当子弹发生碰撞时,我们将回收它。
public class Bullet : MonoBehaviour
{
void OnCollisionEnter(Collider other)
{
//De-activate the object and return it to the spawn pool
gameObject.Recycle();
//You can also use this:
//this.Recycle();
}
}
函数Spawn()被创建的对象的引用, 所以你能够存储这个对象或者调用它的其它方法. 这个函数不像Unity的 Instantiate(), 你不须要强制类型转换得到 GameObject or Component.
小心用回收的对象!
如今,您的对象正在被回收和又一次使用,你必须要小心,由于假设您的实例有不论什么变量被改变。您必须手动重置它们。你能够通过使用Unity提供的的 OnEnable() 和 OnDisable() 函数,仅仅要您的实例使用spawned or recycled函数将会触发OnEnable() 和 OnDisable()。
比如。这是不对的:
public class Bullet : MonoBehaviour
{
public float travelDuration;
float timer = 0; //Only gets set to zero once!
void Update()
{
timer += Time.deltaTime;
if (timer >= travelDuration)
{
gameObject.Recycle();
}
}
}
为什么不对呢?
由于我们的timer变量计数。但永远不会返回到零!所以当回收并在此使用时,它已经不是最開始的状态了。
我们能够非常easy解决问题:
public class Bullet : MonoBehaviour
{
public float travelDuration;
float timer;
void OnEnable()
{
//Correct! Now timer resets every single time:
timer = 0;
}
void Update()
{
timer += Time.deltaTime;
if (timer >= travelDuration)
{
gameObject.Recycle();
}
}
}
如今我们的子弹正确重置他的timer变量。
你能通过对象引用预制体,在曾经是不能的
GameObject如今有组件的扩展方法
InitialPoolSize 參数已加入到 CreatePool()函数总,并告诉它要预先实例化多少的对象,这些都是最初被隐藏和延迟生成的。
您还能够将 ObjectPool 附加到一个游戏对象,通过inspector 设置要 预先实例化 的预制体
附加函数已经加入了用于搜索/统计 实例对象
假设你想要 RecycleAll 要使用派生类型,然后更改这:
var active = instance.prefabLookup.Keys.Where(p => p.GetType() == typeof(T).ToList();
to:
var active = instance.prefabLookup.Keys.Where(p => p is T).ToList();
也适用于 GetAllOfType 的相似的变化
Unity ----- 对象池GameObjectPool的更多相关文章
- Unity 对象池 生产 保存
Unity对象池主要是保存那些常用的物体,避免他们在不断销毁和创造中损坏性能. 主要思路为:创造物体时,判断是否存在,如果存在则调用并使其显示.如果不存在则创造一个新的. 当销毁时,调用协程延时隐藏物 ...
- Unity——对象池管理
Unity对象池管理 一.Demo展示 二.逻辑 在游戏中会出现大量重复的物体需要频繁的创建和销毁:比如子弹,敌人,成就列表的格子等: 频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性 ...
- Unity 对象池的使用
在游戏开发过程中,我们经常会遇到游戏发布后,测试时玩着玩着明显的感觉到有卡顿现象.出现这种现象的有两个原因:一是游戏优化的不够好或者游戏逻辑本身设计的就有问题,二是手机硬件不行.好吧,对于作为程序员的 ...
- Unity对象池的实现
对象池是一个单例类: using System.Collections; using System.Collections.Generic; using UnityEngine; public cla ...
- 游戏设计模式——Unity对象池
对象池这个名字听起来很玄乎,其实就是将一系列需要反复创建和销毁的对象存储在一个看不到的地方,下次用同样的东西时往这里取,类似于一个存放备用物质的仓库. 它的好处就是避免了反复实例化个体的运算,能减少大 ...
- Unity对象池管理
链接: http://www.xuanyusong.com/archives/2925 http://www.xuanyusong.com/archives/2974 https://www.cnbl ...
- GameObjectPool——Unity中的对象池
这里介绍一种对象池的写法.它的优点在于无论取出还是插入游戏物体都是常数量时间. using UnityEngine; using System.Collections; using System.Co ...
- Unity中对象池的使用
unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...
- Unity中的万能对象池
本文为博主原创文章,欢迎转载.请保留博主链接http://blog.csdn.net/andrewfan Unity编程标准导引-3.4 Unity中的万能对象池 本节通过一个简单的射击子弹的示例来介 ...
随机推荐
- 基础训练 Huffuman树
Huffuman树 /*解法一*/ #include<iostream> #include<queue> using namespace std; int main(){ pr ...
- PAT Basic 1066
1066 图像过滤 图像过滤是把图像中不重要的像素都染成背景色,使得重要部分被凸显出来.现给定一幅黑白图像,要求你将灰度值位于某指定区间内的所有像素颜色都用一种指定的颜色替换. 输入格式: 输入在第一 ...
- PAT Basic 1031
1031 查验身份证(15)(15 分) 一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8, ...
- 【11】把 GitHub 当 CMS 用
把 GitHub 当 CMS 用 你的网站需要显示一些文字,但是你还不想直接放在 HTML 里面,那你可以把 GitHub 作为你储存内容的一个地方. 这样,就可以让任何一个非程序员通过修改 Mark ...
- 脑阔疼的双层SQLserver游标
本来简单的双层游标没啥的,内层游标需要读取的是视图的内容,一直报“当前命令发生了严重错误.应放弃任何可能产生的结果.”的错误.无可奈何尝试先将视图的数据放到表变量中,之后再用游标遍历表变量. 简直很怀 ...
- .NET重构(一):抽象工厂模式实现登录
导读:一路艰辛,我也走到了重构.在重构之前,师傅让用经典三层(UI.BLL.DAL)敲了登录.用户的增删改查,共五条线.从开始对三层的朦胧,到五条线结束,终于对三层有了逻辑上清晰的理解.然后就画了几天 ...
- Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"
在iOS上开发视频操作的时候,出现错误: 录制视频错误:Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成" Us ...
- 【倒跑并查集维护连通块】NCPC 2016 A. Artwork
http://codeforces.com/gym/101550/attachments [AC] #include<bits/stdc++.h> using namespace std; ...
- uva 12304点与直线与圆之间的关系
Problem E 2D Geometry 110 in 1! This is a collection of 110 (in binary) 2D geometry problems. Circum ...
- angular中关于自定义指令——repeat渲染完成后执行动作
业务中有时需要在异步获取数据并用ng-repeat遍历渲染完页面后执行某个操作,angular本身并没有提供监听ng-repeat渲染完成的指令,所以需要自己动手写.有经验的同学都应该知道,在ng-r ...