1
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 子弹专用对象池 — 按 prefab 实例ID 分桶,与鱼的 Pool 完全隔离
|
||||
/// 用法:
|
||||
/// var go = BulletPool.Instance.Get(prefab, pos, rot, parent);
|
||||
/// BulletPool.Instance.Return(go); // 代替 Destroy
|
||||
/// </summary>
|
||||
public class BulletPool : Singleton<BulletPool>
|
||||
{
|
||||
// prefab.GetInstanceID() → 该 prefab 的池
|
||||
private Dictionary<int, BulletPoolData> dic = new Dictionary<int, BulletPoolData>();
|
||||
|
||||
// 每个池子的最大缓存数(超出直接 Destroy,防止内存膨胀)
|
||||
private const int MaxCachePerPrefab = 200;
|
||||
|
||||
// 池子根节点(隐藏在场景里)
|
||||
private GameObject poolRoot;
|
||||
|
||||
/// <summary>从池中取一个子弹(池空则 Instantiate)</summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation, Transform parent)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
|
||||
int id = prefab.GetInstanceID();
|
||||
GameObject obj;
|
||||
|
||||
if (dic.TryGetValue(id, out var data) && data.poolList.Count > 0)
|
||||
{
|
||||
obj = data.GetObj();
|
||||
obj.transform.position = position;
|
||||
obj.transform.rotation = rotation;
|
||||
obj.transform.SetParent(parent, false);
|
||||
obj.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = GameObject.Instantiate(prefab, position, rotation, parent);
|
||||
obj.SetActive(true);
|
||||
}
|
||||
|
||||
// 确保挂上 tracker 记录 prefabID(回收时凭此找到对应池)
|
||||
var tracker = obj.GetComponent<BulletPoolTracker>();
|
||||
if (tracker == null)
|
||||
tracker = obj.AddComponent<BulletPoolTracker>();
|
||||
tracker.prefabID = id;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>无 parent 重载</summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation)
|
||||
{
|
||||
return Get(prefab, position, rotation, null);
|
||||
}
|
||||
|
||||
/// <summary>回收子弹到池(超容量则 Destroy)</summary>
|
||||
public void Return(GameObject obj)
|
||||
{
|
||||
if (obj == null) return;
|
||||
|
||||
var tracker = obj.GetComponent<BulletPoolTracker>();
|
||||
int id = tracker != null ? tracker.prefabID : 0;
|
||||
|
||||
// 取不到 id → 兜底 Destroy(非池内对象)
|
||||
if (id == 0)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dic.TryGetValue(id, out var data))
|
||||
dic[id] = data = new BulletPoolData(EnsurePoolRoot().transform, id);
|
||||
|
||||
if (data.poolList.Count >= MaxCachePerPrefab)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
// 重置子弹状态(若有 BullitMove 组件)
|
||||
var bm = obj.GetComponent<BullitMove>();
|
||||
if (bm != null) bm.ResetState();
|
||||
|
||||
data.PushObj(obj);
|
||||
}
|
||||
|
||||
/// <summary>预加载 N 个某 prefab 到池</summary>
|
||||
public void Preload(GameObject prefab, int count)
|
||||
{
|
||||
if (prefab == null || count <= 0) return;
|
||||
int id = prefab.GetInstanceID();
|
||||
|
||||
if (!dic.TryGetValue(id, out var data))
|
||||
dic[id] = data = new BulletPoolData(EnsurePoolRoot().transform, id);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var obj = GameObject.Instantiate(prefab, EnsurePoolRoot().transform);
|
||||
var tracker = obj.GetComponent<BulletPoolTracker>();
|
||||
if (tracker == null)
|
||||
tracker = obj.AddComponent<BulletPoolTracker>();
|
||||
tracker.prefabID = id;
|
||||
data.PushObj(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>清理所有子弹池(切场景时调用)</summary>
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var kv in dic.Values)
|
||||
kv.Clear();
|
||||
dic.Clear();
|
||||
|
||||
if (poolRoot != null)
|
||||
{
|
||||
GameObject.Destroy(poolRoot);
|
||||
poolRoot = null;
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject EnsurePoolRoot()
|
||||
{
|
||||
if (poolRoot == null)
|
||||
{
|
||||
poolRoot = new GameObject("[BulletPool]");
|
||||
poolRoot.SetActive(false); // 池根节点隐藏,池内对象跟随隐藏
|
||||
}
|
||||
return poolRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>挂在池内对象上,记录所属 prefabID(回收时凭此找到对应池)</summary>
|
||||
public class BulletPoolTracker : MonoBehaviour
|
||||
{
|
||||
public int prefabID;
|
||||
}
|
||||
|
||||
/// <summary>单个 prefab 的子弹池数据</summary>
|
||||
public class BulletPoolData
|
||||
{
|
||||
public Transform fatherObj;
|
||||
public List<GameObject> poolList;
|
||||
|
||||
public BulletPoolData(Transform root, int id)
|
||||
{
|
||||
fatherObj = new GameObject("bulletPool_" + id).transform;
|
||||
fatherObj.SetParent(root, false);
|
||||
poolList = new List<GameObject>();
|
||||
}
|
||||
|
||||
public void PushObj(GameObject obj)
|
||||
{
|
||||
if (obj == null) return;
|
||||
poolList.Add(obj);
|
||||
obj.transform.SetParent(fatherObj, false);
|
||||
obj.SetActive(false);
|
||||
}
|
||||
|
||||
public GameObject GetObj()
|
||||
{
|
||||
GameObject obj = poolList[poolList.Count - 1];
|
||||
poolList.RemoveAt(poolList.Count - 1);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var obj in poolList)
|
||||
{
|
||||
if (obj != null) GameObject.Destroy(obj);
|
||||
}
|
||||
poolList.Clear();
|
||||
|
||||
if (fatherObj != null)
|
||||
GameObject.Destroy(fatherObj.gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b450d462c4ecd3349b396f1ff2014f40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
@@ -17,11 +17,12 @@ public class PoolData
|
||||
|
||||
public void PushObj(GameObject obj,int id)
|
||||
{
|
||||
obj.SetActive(false);
|
||||
// 先实例化,再隐藏(原代码对 prefab 调 SetActive(false) 无效且语义混乱)
|
||||
obj = GameObject.Instantiate(obj);
|
||||
obj.name = id.ToString();
|
||||
poolList.Add(obj);
|
||||
obj.transform.parent = fatherObj.transform;
|
||||
obj.SetActive(false);
|
||||
poolList.Add(obj);
|
||||
}
|
||||
public void PushObj(GameObject obj)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user