franciscochonge 发表于 2022-3-26 11:21

Unity中,专用于GameObject的简易对象池

需求

外部传入GameObject模板,从对象池中获取该模板的实例进行使用;
使用完毕后,传入模板和之前获取的实例,将该实例还给对象池。
思路

对象池持有一个字典:模板-对象池元素集合
对象池元素集合是自己写的一个类:其中维护了模板对应的具体实例。
用法

外部在游戏开始时主动Init对象池,游戏结束时主动Destroy对象池。
从对象池中获取实例后,需自行SetActive(true)该实例。
返还实例时,需传入正确的实例对应的模板(对象池本身无法检查传入的是否是正确的。也可通过其他方式检测,如为每个实例添加用于标记的Component)。
具体代码

using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 外界可以传入GO模板,获取GO实例/// </summary>public class GOPool : MonoBehaviour{    public static GOPool Instance{ get; private set; }    private Dictionary<GameObject, GOPoolObj> _goPoolDict;    public static void Init()    {      if (Instance == null)      {            GameObject go = new GameObject(nameof(GOPool));            Instance = go.AddComponent<GOPool>();            Instance._goPoolDict = new Dictionary<GameObject, GOPoolObj>();      }      else      {            Debug.Log("已有Instance,不可再次Init。若确需Init,请先调用Destroy!");      }    }    public void Destroy()    {      foreach (var value in _goPoolDict.Values)      {            value.Destroy();      }      _goPoolDict.Clear();      _goPoolDict = null;      Instance = null;    }    public GameObject GetInstance(GameObject goTemplate)    {      EnsureDictHasKey(goTemplate);      return _goPoolDict.GetInstance();    }    public void RecycleInstance(GameObject goTemplate, GameObject go)    {      EnsureDictHasKey(goTemplate);      _goPoolDict.RecycleInstance(go);    }    private void EnsureDictHasKey(GameObject key)    {      if (!_goPoolDict.ContainsKey(key))      {            var go = new GameObject(key.name);            go.transform.SetParent(transform);            var goPoolObj = new GOPoolObj(go, key);            _goPoolDict.Add(key, goPoolObj);      }    }    private class GOPoolObj    {      private readonly GameObject MyGo;      private readonly GameObject GOTemplate;      private List<GameObject> _gos;      public GOPoolObj(GameObject myGo, GameObject goTemplate)      {            MyGo = myGo;            GOTemplate = goTemplate;            _gos = new List<GameObject>();      }      public void Destroy()      {            _gos.Clear();            _gos = null;            GameObject.Destroy(MyGo);      }      public GameObject GetInstance()      {            if (_gos.Count == 0)            {                var instance = Instantiate(GOTemplate, MyGo.transform);                instance.name = GOTemplate.name + "_0";                _gos.Add(instance);            }            var go = _gos;            _gos.RemoveAt(0);            return go;      }      public void RecycleInstance(GameObject go)      {            go.name = GOTemplate.name + "_" + _gos.Count;            go.transform.SetParent(MyGo.transform);            go.transform.localPosition = Vector3.zero;            go.transform.localRotation = Quaternion.identity;            go.transform.localScale = Vector3.one;            go.SetActive(false);            _gos.Add(go);      }    }}
页: [1]
查看完整版本: Unity中,专用于GameObject的简易对象池