unity 對象池編寫

   先聊聊對象池吧 ,說白了就是我們把經常實例化的東西經常實例 然後又刪除。這應該是常人的操作吧。而對象池的作用就是把後面哪一部分放到一個list裏面,把它設置成setactive(false)。當我們再實例的時候然後從list中取。總體來說很簡單。
   首先我們假如要生成一個子彈,過會我們需要生產一個炮彈,對於這2中物體,我們應該生成2個池子 然後用一個總池子去管理這2個小池子了,這些應該很好理解吧,當然這個池子在任何時候都可以被調用,所以這個池子應該是個單例。我建議單例 最好去用單例組件那樣去寫。至於單例組件怎麼寫,我在下次 消息出來機制中給大家詳細的講。這裏有不講了。
  首先我們先看一下一個小池子的書寫吧,我們定義這個類爲objectpool。這個池子應該有最基本的3個方法吧 首先初始化吧。這讓我們知道這個池子裏面是回收什麼的,是可以生成什麼的。接下來就是實例化一個遊戲物體方法,回收一個遊戲物體。同時也應該有一些輔助方法。例如將池子銷燬掉方法,說實在的話 不知道怎麼和你們講具體的代碼 ,我還是貼代碼。然後再代碼中去講解吧。
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;


public class ObjectPool
{
    public event Action<GameObject> OnSpawnedEvent;
    public event Action<GameObject> onDespawnedEvent;


    public GameObject Prefab;//註釋這個池子裏面的原始東西。這個物體時子彈的話 ,那麼這個池子就只生成和銷燬子彈了。
    public int InstancesToPreallocate = 5;//池子裏面最多能有個數
    public int InstancesToAllocateIfEmpty = 1;//池子最少的個數

    public int HardLimit = 5;//最多限制個數
    public int InstancesToMaintainInPool = 5;
    public bool PersistBetweenScenes = false;


    private Stack<GameObject> _gameObjectPool;




    public void Initialize()//初始化池子
    {
        _gameObjectPool = new Stack<GameObject>(InstancesToPreallocate);
        AllocateGameObjects(InstancesToPreallocate);
    }


    public void ClearStack()//這裏池子用的數據結構是棧  你也可以用鏈表,隊列都行。這個方法是清空棧
    {
        if (_gameObjectPool.Count > InstancesToMaintainInPool)
        {
            for (int i = InstancesToMaintainInPool; i < _gameObjectPool.Count; i++)
            {
                Object.Destroy(_gameObjectPool.Pop());
            }
        }
    }


    public GameObject Spawn()//實例化一個遊戲物體
    {


        var go = Pop();
        return go;
    }


    public void RecycleObj(GameObject ob)//回收一個遊戲物體,將物體設置成不可見,然後放到棧中
    {
        ob.transform.parent = Pools.Instance.gameObject.transform;
        ob.SetActive(false);
        _gameObjectPool.Push(ob);
    }
    private GameObject Pop()
    {
        if (_gameObjectPool.Count > 0)
        {
            return _gameObjectPool.Pop();
        }
        AllocateGameObjects(InstancesToAllocateIfEmpty);
        return Pop();
    }


    public void ClearPool(bool shouldDestroyAllManagedObjects)//qing
    {
        while (_gameObjectPool.Count > 0)
        {
            var go = _gameObjectPool.Pop();
            if (shouldDestroyAllManagedObjects)
                Object.Destroy(go);
        }
    }
    private void AllocateGameObjects(int  count)
    {
        for (int n = 0; n < count; n++)
        {
            GameObject go = Object.Instantiate(Prefab.gameObject) as GameObject;
            go.name = Prefab.name;
            if (go.transform as RectTransform)
            {
                go.transform.SetParent(Pools.Instance.Transform, false);
                go.SetActive(false);
            }
            else
            {
                go.transform.parent = Pools.Instance.Transform;
                go.SetActive(false);
            }
            _gameObjectPool.Push(go);
        }
    }
 

}
當我們在看別人的代碼結構的時候 一些私有方法是可以不用看的,當你要具體瞭解某個類的作用的時候,這是纔開始看。當然接口是最需要看。這只是一種類型物體的池子。我們下節看一個主管理池子的大池子。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章