孙广东 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的更多相关文章

  1. Unity 对象池 生产 保存

    Unity对象池主要是保存那些常用的物体,避免他们在不断销毁和创造中损坏性能. 主要思路为:创造物体时,判断是否存在,如果存在则调用并使其显示.如果不存在则创造一个新的. 当销毁时,调用协程延时隐藏物 ...

  2. Unity——对象池管理

    Unity对象池管理 一.Demo展示 二.逻辑 在游戏中会出现大量重复的物体需要频繁的创建和销毁:比如子弹,敌人,成就列表的格子等: 频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性 ...

  3. Unity 对象池的使用

    在游戏开发过程中,我们经常会遇到游戏发布后,测试时玩着玩着明显的感觉到有卡顿现象.出现这种现象的有两个原因:一是游戏优化的不够好或者游戏逻辑本身设计的就有问题,二是手机硬件不行.好吧,对于作为程序员的 ...

  4. Unity对象池的实现

    对象池是一个单例类: using System.Collections; using System.Collections.Generic; using UnityEngine; public cla ...

  5. 游戏设计模式——Unity对象池

    对象池这个名字听起来很玄乎,其实就是将一系列需要反复创建和销毁的对象存储在一个看不到的地方,下次用同样的东西时往这里取,类似于一个存放备用物质的仓库. 它的好处就是避免了反复实例化个体的运算,能减少大 ...

  6. Unity对象池管理

    链接: http://www.xuanyusong.com/archives/2925 http://www.xuanyusong.com/archives/2974 https://www.cnbl ...

  7. GameObjectPool——Unity中的对象池

    这里介绍一种对象池的写法.它的优点在于无论取出还是插入游戏物体都是常数量时间. using UnityEngine; using System.Collections; using System.Co ...

  8. Unity中对象池的使用

    unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...

  9. Unity中的万能对象池

    本文为博主原创文章,欢迎转载.请保留博主链接http://blog.csdn.net/andrewfan Unity编程标准导引-3.4 Unity中的万能对象池 本节通过一个简单的射击子弹的示例来介 ...

随机推荐

  1. python--操作系统介绍,进程的创建(并发)

    一 .  操作系统的作用: 1:隐藏丑陋复杂的硬件接口,提供良好的抽象接口 2:管理.调度进程,并且将多个进程对硬件的竞争变得有序 二 多道技术: 所谓多道程序设计技术,就是指允许多个程序同时进入内存 ...

  2. Java的9种基本数据类型以及封装类

    Java的9种基本数据类型以及封装类 基本类型 大小(单位/字节) 默认值 封装类 byte 1 (byte)0 Byte short 2 (short)0 Short int 4 0 Integer ...

  3. 使用Lucene的api将索引创建到索引库中

    import org.apache.commons.io.FileUtils; import org.apache.lucene.document.Document; import org.apach ...

  4. Linux下安装Oracle客户端

    1.创建用户名和组名 /usr/sbin/groupadd oinstall /usr/sbin/groupadd dba /usr/sbin/useradd -m -g oinstall -G db ...

  5. python中判断字符串是否为中文

    判断字符串是否在中文编码范围内 for c in s:        if not ('\u4e00' <= c <= '\u9fa5'):            return False ...

  6. 【04】图解JSON

    [04]图解JSON   附件列表

  7. Matplotlib基本图形之条形图

    Matplotlib基本图形之条形图 条形图特点: 以长方形的长度为变量的统计图表用来比较多个数据分类的数据大小通常用于较小的数据集分析例如不同季度的销量,不同国家的人口 示例代码: import o ...

  8. SPOJ - ADALIST,双端队列入门模板!

    ADALIST - Ada and List 这道题时限6.5s,激动人心啊,好多人STL一顿乱写AC,哈哈,如果熟悉双端队列的话这道题其实是很水的. 题意:n个数的数列,然后接下来Q次操作,每次可以 ...

  9. 使用镜像源安装EASY_INSTALL和PIP教程

    使用easy_install和pip可以让python的模块的安装和管理变得非常方便.我一般在新的Linux系统上,先easy_install pip然后就用pip安装其他的模块了. 不过,在国内用官 ...

  10. java解决前后台跨域问题

    这篇文章主要介绍了使用Cors实现JavaWeb跨域请求问题的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下 之前用jsonp 解决跨域问题,现在用CORS实现跨域请求解决java 跨域问题: ...