unity 对象池技术

 我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,引用对象池技术,顾名思义,把所有要用到的对象在初始化的时候都扔到这个池子里,想用的时候拿出来用,不想用的时候放回去,这样会大大节省资源,我在蛮牛上看到一个写对象池不错的code,拿来分享一下。   这个脚本非常简单,但它可以通过大量减少实例化所带来的开销使我的iOS游戏得到很大的性能提升。
  
  • 把脚本ObjectPool.cs链接到一个GameObject上。
  • 在物体预设数组中设置你想要放到池中并重复利用的预设物体。
  • 在缓冲数组中,指定你希望每个物体在游戏开始时被实例化的数量,这样在开始的时候你就有了池对象。
  • 在你的游戏中调用ObjectPool.instance.GetObjectForType(objectType,onlyPooled)来使用它。objectType写你想生成的预设的名字、并为onlyPooled指定布尔值,如果返回真,它将返回你已经放到池中的对象;如果返回假,它将实例化一个全新的对象。(如果你想限制被池对象的数量,那么设定为真,这样做非常有用,尤其是在需要限制同时播放特效的数量的时候)。
  • 确保你从池中调用的对象知道当它被删除时需要返回到池中。
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
      
    public class ObjectPool : MonoBehaviour
    {
      
        public static ObjectPool instance;
      
        /// <summary>
        /// The object prefabs which the pool can handle.
        /// </summary>
        public GameObject[] objectPrefabs;
      
        /// <summary>
        /// The pooled objects currently available.
        /// </summary>
        public List<GameObject>[] pooledObjects;
      
        /// <summary>
        /// The amount of objects of each type to buffer.
        /// </summary>
        public int[] amountToBuffer;
      
        public int defaultBufferAmount = 3;
      
        /// <summary>
        /// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
        /// </summary>
        protected GameObject containerObject;
      
        void Awake ()
        {
            instance = this;
        }
      
        // Use this for initialization
        void Start ()
        {
            containerObject = new GameObject("ObjectPool");
      
            //Loop through the object prefabs and make a new list for each one.
            //We do this because the pool can only support prefabs set to it in the editor,
            //so we can assume the lists of pooled objects are in the same order as object prefabs in the array
            pooledObjects = new List<GameObject>[objectPrefabs.Length];
      
            int i = 0;
            foreach ( GameObject objectPrefab in objectPrefabs )
            {
                pooledObjects[i] = new List<GameObject>(); 
      
                int bufferAmount;
      
                if(i < amountToBuffer.Length) bufferAmount = amountToBuffer[i];
                else
                    bufferAmount = defaultBufferAmount;
      
                for ( int n=0; n<bufferAmount; n++)
                {
                    GameObject newObj = Instantiate(objectPrefab) as GameObject;
                    newObj.name = objectPrefab.name;
                    PoolObject(newObj);
                }
      
                i++;
            }
        }
      
        /// <summary>
        /// Gets a new object for the name type provided.  If no object type exists or if onlypooled is true and there is no objects of that type in the pool
        /// then null will be returned.
        /// </summary>
        /// <returns>
        /// The object for type.
        /// </returns>
        /// <param name='objectType'>
        /// Object type.
        /// </param>
        /// <param name='onlyPooled'>
        /// If true, it will only return an object if there is one currently pooled.
        /// </param>
        public GameObject GetObjectForType ( string objectType , bool onlyPooled )
        {
            for(int i=0; i<objectPrefabs.Length; i++)
            {
                GameObject prefab = objectPrefabs[i];
                if(prefab.name == objectType)
                {
      
                    if(pooledObjects[i].Count > 0)
                    {
                        GameObject pooledObject = pooledObjects[i][0];
                        pooledObjects[i].RemoveAt(0);
                        pooledObject.transform.parent = null;
                        pooledObject.SetActiveRecursively(true);
      
                        return pooledObject;
      
                    } else if(!onlyPooled) {
                        return Instantiate(objectPrefabs[i]) as GameObject;
                    }
      
                    break;
      
                }
            }
      
            //If we have gotten here either there was no object of the specified type or non were left in the pool with onlyPooled set to true
            return null;
        }
      
        /// <summary>
        /// Pools the object specified.  Will not be pooled if there is no prefab of that type.
        /// </summary>
        /// <param name='obj'>
        /// Object to be pooled.
        /// </param>
        public void PoolObject ( GameObject obj )
        {
            for ( int i=0; i<objectPrefabs.Length; i++)
            {
                if(objectPrefabs[i].name == obj.name)
                {
                    obj.SetActiveRecursively(false);
                    obj.transform.parent = containerObject.transform;
                    pooledObjects[i].Add(obj);
                    return;
                }
            }
        }
      
    }

    转载:http://www.unitymanual.com/thread-36644-1-1.html
Unity 中的对象池是一种资源管理技术,用于在游戏运行过程中高效地创建、管理和回收对象。对象池的主要目的是减少频繁创建和销毁对象带来的性能开销,尤其是在有大量短期使用对象(如小敌人、项目等)的情况下。 下面是使用 Unity 对象池的基本步骤: 1. 创建对象池:首先,你需要创建一个包含所需对象类型的新对象池。这通常是一个静态类或专用脚本,负责管理对象的生命周期。 ```csharp public class ObjectPool<T> where T : Component { private List<T> poolObjects; private Stack<T> availableObjects; // 初始化方法 public ObjectPool(int initialSize) { poolObjects = new List<T>(); for (int i = 0; i < initialSize; i++) { T obj = Instantiate<T>(); obj.SetActive(false); // 设置对象为非活动状态,直到需要时才激活 poolObjects.Add(obj); } availableObjects = new Stack<T>(poolObjects); } // 获取对象 public T BorrowObject() { if (availableObjects.Count > 0) { T obj = availableObjects.Pop(); obj.SetActive(true); return obj; } else { T obj = Instantiate<T>(); return obj; } } // 归还对象 public void ReturnObject(T obj) { obj.SetActive(false); availableObjects.Push(obj); } } ``` 2. 使用对象池:当你需要一个新对象时,从池中借用一个,用完后记得归还。这样,当对象不再被使用时,它会被放回池而不是直接销毁,以便后续其他地方可能需要它。 ```csharp private ObjectPool<MyObject> objectPool; void Start() { objectPool = new ObjectPool<MyObject>(10); } void Update() { MyObject newObj = objectPool.BorrowObject(); // 使用 newObj ... newObj.gameObject.SetActive(false); // 当对象不再需要时,归还给池子 // 如果对象池已满,考虑创建更多对象 if (objectPool.availableObjects.Count == 0 && poolSize < MaxPoolSize) { // 添加新对象到池中 objectPool.poolObjects.Add(Instantiate<MyObject>()); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值