237 lines
6.9 KiB
C#
237 lines
6.9 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 鱼对象池 - 复用鱼对象避免频繁 Instantiate/Destroy
|
||
/// </summary>
|
||
public class FishObjectPool : MonoBehaviour
|
||
{
|
||
public static FishObjectPool Instance { get; private set; }
|
||
|
||
[System.Serializable]
|
||
public class PoolConfig
|
||
{
|
||
public FishType fishType;
|
||
public int initialSize = 5; // 初始池大小
|
||
public int maxSize = 20; // 最大池大小
|
||
}
|
||
|
||
[Header("对象池配置")]
|
||
public List<PoolConfig> poolConfigs = new List<PoolConfig>();
|
||
|
||
// 对象池字典:FishType -> 对象队列
|
||
private Dictionary<FishType, Queue<GameObject>> fishPools = new Dictionary<FishType, Queue<GameObject>>();
|
||
private Dictionary<FishType, PoolConfig> configMap = new Dictionary<FishType, PoolConfig>();
|
||
|
||
// 记录从池中取出的对象,用于回收时识别类型
|
||
private Dictionary<GameObject, FishType> activeFishMap = new Dictionary<GameObject, FishType>();
|
||
|
||
void Awake()
|
||
{
|
||
Instance = this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化对象池 - 在游戏开始前调用
|
||
/// </summary>
|
||
public void InitializePools()
|
||
{
|
||
// 构建配置映射
|
||
foreach (var config in poolConfigs)
|
||
{
|
||
configMap[config.fishType] = config;
|
||
}
|
||
|
||
// 为每种配置的鱼创建初始池
|
||
foreach (var config in poolConfigs)
|
||
{
|
||
CreatePool(config.fishType, config.initialSize);
|
||
}
|
||
|
||
Debug.Log($"[FishObjectPool] 对象池初始化完成,共 {poolConfigs.Count} 种鱼类型");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建指定类型的对象池
|
||
/// </summary>
|
||
void CreatePool(FishType fishType, int size)
|
||
{
|
||
fishPools[fishType] = new Queue<GameObject>();
|
||
|
||
int fishId = (int)fishType;
|
||
GameObject prefab = GameManager.Ins.GetFishPre(fishId - 1);
|
||
|
||
if (prefab == null)
|
||
{
|
||
Debug.LogError($"[FishObjectPool] 找不到鱼预制体: {fishType}");
|
||
return;
|
||
}
|
||
|
||
// 预创建对象
|
||
for (int i = 0; i < size; i++)
|
||
{
|
||
GameObject fish = Instantiate(prefab, transform);
|
||
|
||
// 禁用 SplineController,防止在隐藏状态下运行并报错
|
||
var splineController = fish.GetComponent<FluffyUnderware.Curvy.Controllers.SplineController>();
|
||
if (splineController != null)
|
||
{
|
||
splineController.enabled = false;
|
||
}
|
||
|
||
fish.SetActive(false);
|
||
fishPools[fishType].Enqueue(fish);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从对象池获取鱼
|
||
/// </summary>
|
||
public GameObject GetFish(FishType fishType)
|
||
{
|
||
// 确保池存在
|
||
if (!fishPools.ContainsKey(fishType))
|
||
{
|
||
// 如果没有配置,使用默认配置创建
|
||
var config = new PoolConfig { fishType = fishType, initialSize = 3, maxSize = 10 };
|
||
configMap[fishType] = config;
|
||
CreatePool(fishType, config.initialSize);
|
||
}
|
||
|
||
var pool = fishPools[fishType];
|
||
GameObject fish = null;
|
||
|
||
// 从池中取出一个可用的对象
|
||
while (pool.Count > 0)
|
||
{
|
||
fish = pool.Dequeue();
|
||
if (fish != null) // 防止对象已被销毁
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 池为空则创建新对象
|
||
if (fish == null)
|
||
{
|
||
int fishId = (int)fishType;
|
||
GameObject prefab = GameManager.Ins.GetFishPre(fishId - 1);
|
||
if (prefab != null)
|
||
{
|
||
fish = Instantiate(prefab);
|
||
Debug.Log($"[FishObjectPool] 池为空,创建新对象: {fishType}");
|
||
}
|
||
}
|
||
|
||
if (fish != null)
|
||
{
|
||
// 在激活前确保 SplineController 被禁用
|
||
// 防止在 Init 设置 Spline 之前 Update 运行
|
||
var splineController = fish.GetComponent<FluffyUnderware.Curvy.Controllers.SplineController>();
|
||
if (splineController != null)
|
||
{
|
||
splineController.enabled = false;
|
||
}
|
||
|
||
fish.SetActive(true);
|
||
activeFishMap[fish] = fishType;
|
||
}
|
||
|
||
return fish;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收鱼到对象池
|
||
/// </summary>
|
||
public void ReturnFish(GameObject fish)
|
||
{
|
||
if (fish == null) return;
|
||
|
||
// 获取鱼的类型
|
||
if (!activeFishMap.TryGetValue(fish, out FishType fishType))
|
||
{
|
||
// 如果找不到类型映射,尝试从 Fish 组件获取
|
||
var fishComponent = fish.GetComponent<Fish>();
|
||
if (fishComponent != null && fishComponent.Data != null)
|
||
{
|
||
fishType = (FishType)fishComponent.Data.FishId;
|
||
}
|
||
else
|
||
{
|
||
// 无法识别类型,直接销毁
|
||
Destroy(fish);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 从活跃映射中移除
|
||
activeFishMap.Remove(fish);
|
||
|
||
// 确保池存在
|
||
if (!fishPools.ContainsKey(fishType))
|
||
{
|
||
fishPools[fishType] = new Queue<GameObject>();
|
||
}
|
||
|
||
var pool = fishPools[fishType];
|
||
var config = configMap.ContainsKey(fishType) ? configMap[fishType] : null;
|
||
|
||
// 如果池未满,回收对象
|
||
if (config == null || pool.Count < config.maxSize)
|
||
{
|
||
// 重置对象状态
|
||
fish.SetActive(false);
|
||
fish.transform.SetParent(transform);
|
||
fish.transform.localPosition = Vector3.zero;
|
||
|
||
// 重置 Fish 组件状态
|
||
var fishComponent = fish.GetComponent<Fish>();
|
||
if (fishComponent != null)
|
||
{
|
||
fishComponent.ResetForPool();
|
||
}
|
||
|
||
pool.Enqueue(fish);
|
||
}
|
||
else
|
||
{
|
||
// 池已满,销毁对象
|
||
Destroy(fish);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空所有对象池
|
||
/// </summary>
|
||
public void ClearAllPools()
|
||
{
|
||
foreach (var pool in fishPools.Values)
|
||
{
|
||
while (pool.Count > 0)
|
||
{
|
||
var fish = pool.Dequeue();
|
||
if (fish != null)
|
||
{
|
||
Destroy(fish);
|
||
}
|
||
}
|
||
}
|
||
fishPools.Clear();
|
||
activeFishMap.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取池状态信息(调试用)
|
||
/// </summary>
|
||
public string GetPoolStatus()
|
||
{
|
||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||
sb.AppendLine("[FishObjectPool] 对象池状态:");
|
||
foreach (var pair in fishPools)
|
||
{
|
||
sb.AppendLine($" {pair.Key}: {pair.Value.Count} 个可用");
|
||
}
|
||
return sb.ToString();
|
||
}
|
||
}
|