我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,引用对象池技术,顾名思义,把所有要用到的对象在初始化的时候都扔到这个池子里,想用的时候拿出来用,不想用的时候放回去,这样会大大节省资源,我在蛮牛上看到一个写对象池不错的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