前面講到一類池子的編寫。這裏有一個主池子。管理下面的小池子他的數據結構的是個字典。假如我們現在要回收一個子彈,那麼首先要在一個主池子中找到子彈這個小池子,然後讓小池子去回收是吧,同理,如果我們要去生成一個東西的話,我們是不是同樣也要去從大池子中找到一個子彈池子,然後讓小池子去生成。多以我們得有一個字典,字典的key應該是預置物的id,value應該是與預置物的池子。同樣這個大池子應該也應該同樣有3個方法,這3個方法應該和小池子基本方法相同,我還是直接提交代碼吧。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Pools : MonoBehaviour
{
public static Pools Instance;
[HideInInspector]
public List<ObjectPool> RecycleBinCollection=new List<ObjectPool>();
private Dictionary<int,ObjectPool> _instanceIdToRecycleBin = new Dictionary<int,ObjectPool>();
private Dictionary<string,int> _poolNameToInstanceId = new Dictionary<string,int>();
[HideInInspector]
public new Transform Transform;
private void Awake()
{
if (Instance != null)
{
Destroy( gameObject );
}
else
{
Transform = gameObject.transform;
Instance = this;
InitializePrefabPools();
}
}
private void OnApplicationQuit()
{
Instance = null;
}
private void OnLevelWasLoaded()
{
for( var i = RecycleBinCollection.Count - 1; i >= 0; i-- )
{
if( !RecycleBinCollection[i].PersistBetweenScenes )
RemoveRecyclePool( RecycleBinCollection[i] );
}
}
public static GameObject Spawn(GameObject go, Vector3 position = default( Vector3 ), Quaternion rotation = default( Quaternion ))
{
if (Instance._instanceIdToRecycleBin.ContainsKey(go.GetInstanceID()))
{
return Spawn(go.GetInstanceID(), position, rotation);
}
else
{
Debug.LogWarning("attempted to spawn go (" + go.name + ") but there is no recycle bin setup for it. Falling back to Instantiate");
var newGo = GameObject.Instantiate(go, position, rotation) as GameObject;
if (newGo != null && newGo.transform is RectTransform)
newGo.transform.SetParent(null, false);
else if (newGo != null) newGo.transform.parent = null;
return newGo;
}
}
public static void ManageRecyclePool(ObjectPool objectPool)
{
if (Instance._poolNameToInstanceId.ContainsKey(objectPool.Prefab.name))
{
Debug.LogError("Cannot manage the recycle bin because there is already a GameObject with the name (" + objectPool.Prefab.name + ") being managed");
return;
}
objectPool.Initialize();
Instance.RecycleBinCollection.Add(objectPool);
Instance._instanceIdToRecycleBin.Add(objectPool.Prefab.GetInstanceID(), objectPool);
Instance._poolNameToInstanceId.Add(objectPool.Prefab.name, objectPool.Prefab.GetInstanceID());
}
public static void RecyclePoolObj(GameObject obj)
{
if (!Instance._poolNameToInstanceId.ContainsKey(obj.name))
{
return;
}
int id = Instance._poolNameToInstanceId[obj.name];
ObjectPool curPool = Instance._instanceIdToRecycleBin[id];
if(curPool!=null)
curPool.RecycleObj(obj);
}
private static GameObject Spawn(int gameObjectInstanceId, Vector3 position, Quaternion rotation)
{
if (Instance._instanceIdToRecycleBin.ContainsKey(gameObjectInstanceId))
{
var newGo = Instance._instanceIdToRecycleBin[gameObjectInstanceId].Spawn();
if (newGo != null)
{
var newTransform = newGo.transform;
if (newTransform as RectTransform)
{
newTransform.SetParent(null, false);
}
else
{
newTransform.parent = null;
newTransform.position = position;
newTransform.rotation = rotation;
}
newGo.SetActive(true);
}
return newGo;
}
return null;
}
private void RemoveRecyclePool(ObjectPool objectPool)
{
var recycleBinName = objectPool.Prefab.name;
if (Instance._poolNameToInstanceId.ContainsKey(recycleBinName))
{
Instance._poolNameToInstanceId.Remove( recycleBinName );
Instance._instanceIdToRecycleBin.Remove(objectPool.Prefab.GetInstanceID() );
Instance.RecycleBinCollection.Remove(objectPool);
objectPool.ClearPool(true);
}
}
private void InitializePrefabPools()
{
if (RecycleBinCollection == null)
return;
foreach (var recycleBin in RecycleBinCollection)
{
if (recycleBin == null || recycleBin.Prefab == null)
continue;
recycleBin.Initialize();
_instanceIdToRecycleBin.Add(recycleBin.Prefab.GetInstanceID(), recycleBin);
_poolNameToInstanceId.Add(recycleBin.Prefab.name, recycleBin.Prefab.GetInstanceID());
}
}
}
這些代碼比較簡單,前面我都把原理告訴大家,看起來應該蠻簡單的。這個對象池是模仿premiere 31這個公司的插件。如果大家不瞭解這個公司可以去查查。做unity插件很出名的一家公司。大家有興趣的話可以去學習他們的插件,然後寫出自己的插件。