山寨小小军团开发笔记 之 GamePool
很多时候我们对于物体(比如弓箭)大量的生成与销毁,这个时候可以把弓箭放在内存池中进行管理,加快体验。自己Copy了一个简易版的。
一、代码
GameObjectPoolManager.cs
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; // A general pool object for reusable game objects. // // It supports spawning and unspawning game objects that are // instantiated from a common prefab. Can be used preallocate // objects to avoid calls to Instantiate during gameplay. Can // also create objects on demand (which it does if no objects // are available in the pool). public class GameObjectPoolManager { public GameObject parent;
// The prefab that the game objects will be instantiated from. private GameObject prefab;
// The list of available game objects (initially empty by default). private Stack<GameObject> available; // The list of all game objects created thus far (used for efficiently // unspawning all of them at once, see UnspawnAll). private List<GameObject> all; // An optional function that will be called whenever a new object is instantiated. // The newly instantiated object is passed to it, which allows users of the pool // to do custom initialization. private Callback<GameObject> initializeFunction; private Callback<GameObject> destroyFunction; //// Indicates whether the pool's game objects should be activated/deactivated //// recursively (i.e. the game object and all its children) or non-recursively (just the //// game object). //private var setActiveRecursively : boolean; // Creates a pool. // The initialCapacity is used to initialize the .NET collections, and determines // how much space they pre-allocate behind the scenes. It does not pre-populate the // collection with game objects. For that, see the PrePopulate function. // If an initialCapacity that is <= to zero is provided, the pool uses the default // initial capacities of its internal .NET collections. public GameObjectPoolManager(GameObject prefab, Callback<GameObject> initializeFunction, Callback<GameObject> destroyFunction) { this.prefab = prefab; this.parent = new GameObject(prefab.name + "Pool"); this.available = new Stack<GameObject>(); this.all = new List<GameObject>(); this.initializeFunction = initializeFunction; this.destroyFunction = destroyFunction; } // Spawn a game object with the specified position/rotation. public GameObject Spawn(Vector3 position, Quaternion rotation) { GameObject result = null; if (available.Count == 0) { // Create an object and initialize it. result = GameObject.Instantiate(prefab, position, rotation) as GameObject; result.transform.parent = parent.transform; // Keep track of it. all.Add(result); } else { result = available.Pop() as GameObject; // Get the result's transform and reuse for efficiency. //Calling gameObject.transform is expensive. var resultTrans = result.transform; resultTrans.position = position; resultTrans.rotation = rotation; result.SetActive(true); } if (initializeFunction != null) initializeFunction(result); return result; } // Unspawn the provided game object. // The function is idempotent. Calling it more than once for the same game object is // safe, since it first checks to see if the provided object is already unspawned. // Returns true if the unspawn succeeded, false if the object was already unspawned. public bool Unspawn(GameObject obj) { if (!available.Contains(obj)) { // Make sure we don't insert it twice. available.Push(obj); obj.SetActive(false); if (destroyFunction != null) destroyFunction(obj); return true; // Object inserted back in stack. } return false; // Object already in stack. } // Pre-populates the pool with the provided number of game objects. void PrePopulate(int count){ GameObject[] array = new GameObject[count]; for(var i = 0; i < count; i++){ array[i] = Spawn(Vector3.zero, Quaternion.identity); //this.SetActive(array[i], false); } for(var j = 0; j < count; j++){ Unspawn(array[j]); } }
// Unspawns all the game objects created by the pool. void UnspawnAll() { foreach (var item in available) { Unspawn(item); } } // Returns the number of active objects. int GetActiveCount() { return all.Count - available.Count; } // Returns the number of available objects. int GetAvailableCount(){ return available.Count; } }
二、应用
还是用之前的BezierTest.cs的例子
void Start() { arrowPool = new GameObjectPoolManager(arrowPrefab, null, null); //controlPoints = ControlPoints(transform, right); } #endregion void Test(bool fireRight) { Transform end = fireRight ? right : left; ///在中心点生成弓箭 GameObject curArrow = arrowPool.Spawn(transform.position, Quaternion.Euler(Vector3.zero)); ///计算LookTarget的点 与 贝塞尔曲线的第三个控制点 Vector3[] points = Re_LookTarget_MiddlePerpendicularPoint(curArrow.transform, end); ///初始化发射 ArrowControl arrowControl = curArrow.GetComponent<ArrowControl>(); arrowControl.Init( points[0], points[1], end.position, 3.0f, delegate() { arrowPool.Unspawn(curArrow); }); }