【Unity】【转载】对象池的初步理解和运用

本文介绍了对象池的概念及其在Unity3D中的应用。通过减少对象的创建与销毁,提高游戏性能。提供了对象池管理器的实现代码及子弹发射示例。

在我们使用对象池之前我们需要知道以下两点:
1.什么是对象池?
  池(Pool),与集合在某种意义上有些相似。 水池,是一定数量的水的集合;内存池,是一定数量的已经分配好的内存的集合;线程池,是一定数量的已经创建好的线程的集合。那么,对象池,顾名思义就是一定数量的已经创建好的对象(Object)的集合[1]。
  在面向对象过程中,如果一种对象,你要经常使用,并且需要反复创建、销毁,这样子一方面开销会比较大,另一方面会产生很多内存碎片,程序运行时间一过长,性能就会下降。这个时候,就产生了对象池。我们可以事先创建好一批对象,并且放在一个集合中(对象池),以后每当程序需要使用到对象的时候,我们不是创建一个对象,而是从对象池里获取,程序用完该对象后,再把该对象归还给对象池。这样,就会少了很多的关于创建或者销毁的调用,在一定程度上提高了系统的性能,尤其在动态内存分配比较频繁的程序中效果较为明显。

2.Unity3d中的对象池
  在使用unity3d做游戏时,经常有同一个Prefab用到多次,需要反复实例化(Instantiate)。但实例化是很消耗资源的,所以在游戏加载时把一批Prefab实例化好放在对象池中,游戏中用的时候拿出来,不用的时候放回去,避免反复申请和销毁。
  存入对象池的元素应具有如下特征:1>场景中大量使用 2>存在一定的生命周期,会较为频繁的申请和释放。

下面不多说直接上代码:

using System . Collections ;
using System . Collections . Generic ;
using UnityEngine ;
public class ObjectPoolManager : MonoBehaviour {
    // 继承于monoBehaviour的单例可以简化为这样,方便使用
    public static ObjectPoolManager Instance ;
    // 定义一个大池子
    private Dictionary < string , List < GameObject >> pool ;
    void Awake (
    {
        Instance = this ;
    }
    void Start ()
    {
        pool = new Dictionary < string , List < GameObject >>();
    }
   
    // 两个主要方法,存、取
    // 取对象
    public GameObject GetObjectFromPool ( string objName , Vector3 pos , Quaternion qua )
    {
        GameObject go ;
        // 当池子中有相应的键值对,并且里面有可以使用的对象,则直接拿出来用
        if ( pool . ContainsKey ( objName ) && pool [ objName ]. Count > 0)
        {
            // 把相应的键值对中的第一个对象取出来,并从池子中移除
            go = pool [ objName ][0];
            pool [ objName ]. RemoveAt (0);
            // 激活这个对象
            go . SetActive ( true );
        }
        else
        {
            // 若不满足上面条件,则实例化一个新的对象出来
            go = Instantiate ( Resources . Load ( objName ) as GameObject );
        }
        // 设置一下得到的对象的位置以及旋转角度
        go . transform . position = pos ;
        go . transform . rotation = qua ;
        return go ;
    }
    // 存对象(参数为我们即将存入的对象)
    public void PushObjectToPool ( GameObject go )
    {
        string prefabName = go . name . Split ( '(' )[0];
        // 判断池子中有没有相应的键值对,没有则创建一个新的键值对,有则直接往里存
        if ( pool . ContainsKey ( prefabName ))
        {
            pool [ prefabName ]. Add ( go );
        }
        else
        {
            // 在池子中创建一个新的键值对,并初始化List
            pool [ prefabName ] = new List < GameObject >() { go };
        }
        // 取消激活该对象
        go . SetActive ( false );
    }
}


using System . Collections ;
using System . Collections . Generic ;
using UnityEngine ;
public class MyFight : MonoBehaviour {
    // 定义即将生成的预制体名字
    const string redBullet = "RedBullet" ;
    const string blueBullet = "BlueBullet" ;
    // 获取两种子弹生成的位置及角度信息
    public Transform redBulletPos ;
    public Transform blueBulletPos ;
        // Use this for initialization
        void Start () {
              
       }
       
        // Update is called once per frame
        void Update () {
        // 按下鼠标左键生成红色子弹
        if ( Input . GetMouseButtonDown (0))
        {
            // 生成的操作就是取对象的操作
            GameObject go = ObjectPoolManager . Instance . GetObjectFromPool ( redBullet , redBulletPos . position , redBulletPos . rotation );
            // 给子弹加力度
            go . GetComponent < Rigidbody >(). AddForce ( go . transform . forward * 500);
            // 让子弹一秒钟之后消失(放入池子)
            StartCoroutine ( DestroyBullet ( go ));
        }
        // 鼠标右键生成蓝色子弹
        if ( Input . GetMouseButtonDown (1))
        {
            // 生成的操作就是取对象的操作
            GameObject go = ObjectPoolManager . Instance . GetObjectFromPool ( blueBullet , blueBulletPos . position , blueBulletPos . rotation );
            // 给子弹加力度
            go . GetComponent < Rigidbody >(). AddForce ( go . transform . forward * 500);
            // 让子弹一秒钟之后消失(放入池子)
            StartCoroutine ( DestroyBullet ( go ));
        }
       }
       
    IEnumerator DestroyBullet ( GameObject go )
    {
        yield return new WaitForSeconds (1);
        // 重置子弹的速度为0
        go . GetComponent < Rigidbody >(). velocity = Vector3 . zero ;
        ObjectPoolManager . Instance . PushObjectToPool ( go );
    }
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值