美文网首页
Unity中,专用于GameObject的简易对象池

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

作者: 全新的饭 | 来源:发表于2022-03-25 16:38 被阅读0次

需求

外部传入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[goTemplate].GetInstance();
    }
    public void RecycleInstance(GameObject goTemplate, GameObject go)
    {
        EnsureDictHasKey(goTemplate);
        _goPoolDict[goTemplate].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[0];
            _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);
        }
    }
}

相关文章

网友评论

      本文标题:Unity中,专用于GameObject的简易对象池

      本文链接:https://www.haomeiwen.com/subject/pfddjrtx.html