對象池編寫 下篇

    前面講到一類池子的編寫。這裏有一個主池子。管理下面的小池子他的數據結構的是個字典。假如我們現在要回收一個子彈,那麼首先要在一個主池子中找到子彈這個小池子,然後讓小池子去回收是吧,同理,如果我們要去生成一個東西的話,我們是不是同樣也要去從大池子中找到一個子彈池子,然後讓小池子去生成。多以我們得有一個字典,字典的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插件很出名的一家公司。大家有興趣的話可以去學習他們的插件,然後寫出自己的插件。

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章