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中的万能对象池 本节通过一个简单的射击子弹的示例来介 ...
随机推荐
- ZZULIoj 1913: 小火山的计算能力
Description 别人说小火山的计算能力不行,小火山很生气,于是他想证明自己,现在有一个表达式,他想计算出来. Input 首先是一个t(1<=20)表示测试组数.然后一个表达式,表达式长 ...
- PAT Basic 1043
1043 输出PATest 给定一个长度不超过 104 的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符.当然,六种字符的 ...
- Linux文件管理类命令及命令别名
文件查看类命令: cat: tac: 从文件尾部开始显示 分屏显示: more [option] 文件名: 查看至文件尾部会退出 空格为翻页 less [option] 文件名: 查看至文件尾部不退出 ...
- List<T> List<?> 区别用法
List<T>是泛型方法,List<?>是限制通配符 List<T>一般有两种用途:1.定义一个通用的泛型方法.伪代码: public interface Dao{ ...
- http协议工作原理(转)
WWW是以Internet作为传输媒介的一个应用系统,WWW网上最基本的传输单位是Web网页.WWW的工作基于客户机/服务器计算模型,由Web 浏览器(客户机)和Web服务器(服务器)构成,两者之间 ...
- TOJ 4701 求阴影部分面积
4701: 求阴影部分面积 本文版权归BobHuang和博客园共有,不得转载.如想转载,请联系作者,并注明出处. Time Limit(Common/Java):1000MS/3000MS ...
- ubuntu添加开机启动
vim /etc/init.d/mytest #!/bin/sh echo "$(pwd) and $USER and $(whoami)" >> /root/temp ...
- 全库修改SQL Server现有排序规则
近日,在项目Debug过程中发现了SQL Server排序规则冲突的问题. 由于原数据库是从英文环境的SQL中生成的,其排序规则为“SQL_Latin1_General_CP1_CI_AS”,备份到本 ...
- 彻底解决Request Too Long的问题
运行regedit,进入 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\HTTP\Parameters , 1. 添加类型为 DWORD(3 ...
- J2EE 中间件 JVM 集群
[转]J2EE 中间件 JVM 集群 博客分类: 企业应用面临的问题 Java&Socket 开源组件的应用 jvm应用服务器weblogicjvm集群 1 前言 越来越多的关键任务和大型应用 ...