山寨小小军团开发笔记 之 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);
});
}

浙公网安备 33010602011771号