Files
MRFishingMaster/Assets/_FishingMaster/Scripts/Fish/Base/FishObjectPool.cs

221 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
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)
{
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();
}
}