需求
外部传入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);
}
}
}










网友评论