This commit is contained in:
2026-05-01 06:26:50 +08:00
parent 0055207c24
commit dff505d073
263 changed files with 13655 additions and 11640 deletions
@@ -197,9 +197,13 @@ public class MonsterContral : MonoBehaviour
fishenum = (FishTypeEnum)monsterData.fishTypeConfig.fishType;
// 路径结束后自动销毁
Pool.Instance.Return(gameObject, time);
StartCoroutine(yanchi(gameObject,time));
}
public IEnumerator yanchi(GameObject obj,float time)
{
yield return new WaitForSeconds(time);
Pool.Instance.Return(gameObject);
}
// ================================================================
// 状态机
// ================================================================
@@ -317,7 +321,7 @@ public class MonsterContral : MonoBehaviour
transform.position = next;
}
public bool isRotate=true;
/// <summary>
/// 根据 forwordXYZ 字段将物体朝向目标点方向。
/// 为空时 2D 鱼用 up,3D 鱼用 forward。
@@ -325,6 +329,10 @@ public class MonsterContral : MonoBehaviour
/// <param name="nextPos">下一帧目标位置</param>
private void ApplyFacingDirection(Vector2 nextPos)
{
if (!isRotate)
{
return;
}
Vector2 toNext = nextPos - (Vector2)transform.position;
Vector2 fromNext = (Vector2)transform.position - nextPos;
@@ -391,6 +399,7 @@ public class MonsterContral : MonoBehaviour
{
AudioManager.Instance.PlayerFX(res.dieAudio[0]);
}
CreateFishManager.Instance.DieFishList(guid);
Pool.Instance.Return(gameObject);
//Destroy(gameObject);
}
@@ -28,6 +28,7 @@ public class MonsterControl_BossBase : MonsterContral
public override void Awake()
{
base.Awake();
isRotate = false;
ZhuCam = GameManager.Instance.ZhuCam;
}
@@ -133,9 +134,11 @@ public class MonsterControl_BossBase : MonsterContral
}
}
public bool isDieFish=false;
public override void DieFish(RoomKillNotice obj = null)
{
isDieFish = true;
CreateFishManager.Instance.DieFishList(guid);
GameManager.Instance.cameraShake.ShakePresets.Explosion2D(3f, 4f, 1f);
if (obj != null)
{
@@ -151,7 +154,6 @@ public class MonsterControl_BossBase : MonsterContral
int index = Random.Range(0, v.Count);
AudioManager.Instance.PlayerFX(v[index]);
}
Pool.Instance.Return(gameObject);
}
@@ -175,24 +177,24 @@ public class MonsterControl_BossBase : MonsterContral
case GameType.defaultPanel:
break;
case GameType.FLZY:
{
AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
await handle.Task;
Sprite sprite = handle.Result;
CreateFishManager.Instance. currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
//{
// AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
// await handle.Task;
// Sprite sprite = handle.Result;
// CreateFishManager.Instance. currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
}
//}
break;
case GameType.TGXX:
//还没有写呢
{
AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
await handle.Task;
Sprite sprite = handle.Result;
CreateFishManager.Instance.currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
//{
// AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
// await handle.Task;
// Sprite sprite = handle.Result;
// CreateFishManager.Instance.currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
}
//}
break;
case GameType.ZGXQ:
@@ -207,13 +209,13 @@ public class MonsterControl_BossBase : MonsterContral
}
break;
case GameType.HHWK:
{
AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
await handle.Task;
Sprite sprite = handle.Result;
CreateFishManager.Instance.currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
//{
// AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>("Assets/Art/XJMH/pw/pw_sprite/handbook/" + bossName + ".png");
// await handle.Task;
// Sprite sprite = handle.Result;
// CreateFishManager.Instance.currGameType.subUIManager.ShowBoardBoss(sprite, bossName);
}
//}
break;
default:
break;
@@ -224,16 +226,19 @@ public class MonsterControl_BossBase : MonsterContral
public override void OnDisable()
{
base.OnDisable();
if (isDieFish)
{
GameManager.Instance.StartCoroutine(yanchidie());
}
}
public float dieTime = 3f;
public Vector3 v3;
IEnumerator yanchidie()
{
yield return new WaitForSeconds(dieTime);
tMP_CurrBossScore.transform.parent.DOMove(CreateFishManager.Instance.currGameType.currSitData.tMP_GoldNum.transform.position, 0.5f).OnComplete(() =>
tMP_CurrBossScore.transform.parent.DOMove(v3, 0.5f).OnComplete(() =>
{
@@ -23,10 +23,14 @@ public class MonsterMoveLine
public Vector2 end;
}
public static async void LoadBezier()
public static async Task LoadBezier()
{
await LoadBezierTxtAsync("MoveLine");
}
public static async Task UnLoadBezier()
{
await UnLoadBezierTxtAsync("MoveLine");
}
public static async Task LoadSingleBezierTxtAsync(string path)
{
@@ -65,7 +69,9 @@ public class MonsterMoveLine
List<string> keys = new List<string>();
keys.Add(path);
keys.Add(GameManager.Instance.gameData.currGameType.ToString());
AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(keys, null, Addressables.MergeMode.Intersection);
AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(
keys, null, Addressables.MergeMode.Intersection);
await handles.Task;
foreach (var text in handles.Result)
@@ -93,13 +99,51 @@ public class MonsterMoveLine
curve.controlPoints.Add(points[i]);
curves.Add(curve);
dic_BezierCurveDatas.Add(curve.name, curve);
// 改成索引器赋值,避免重复 key 报错
dic_BezierCurveDatas[curve.name] = curve;
}
}
Debug.Log("曲线读取完成共" + dic_BezierCurveDatas.Count + "条");
}
public static async Task UnLoadBezierTxtAsync(string path)
{
List<string> keys = new List<string>();
keys.Add(path);
keys.Add(GameManager.Instance.gameData.currGameType.ToString());
AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(keys, null, Addressables.MergeMode.Intersection);
await handles.Task;
foreach (var text in handles.Result)
{
var lines = text.text.Split('\n');
foreach (var line in lines)
{
if (string.IsNullOrWhiteSpace(line)) continue;
var parts = line.Split(';');
string curveName = parts[0];
// 如果字典里有该曲线,移除
if (dic_BezierCurveDatas.ContainsKey(curveName))
{
dic_BezierCurveDatas.Remove(curveName);
}
// 从列表中移除对应曲线
curves.RemoveAll(c => c.name == curveName);
}
}
// 释放 Addressables 资源
Addressables.Release(handles);
Debug.Log("曲线卸载完成,剩余曲线数量:" + dic_BezierCurveDatas.Count);
}
private static Vector2 ParseVector(string s)
{
var xy = s.Split(',');
@@ -176,7 +176,7 @@ public class BullitMove : MonoBehaviour
var v2 = GameManager.Instance.gameData.currRoomData;
if (true)
{
WebSocketSendList.KillFish(v2.roomId, userid,monster.monsterData.fishTypeConfig.fishNumber, monster.guid, GameManager.Instance.gameData.roomJoinNotice.cannonMultiple);
WebSocketSendList.KillFish(v2.roomId, userid,monster.monsterData.fishTypeConfig.fishNumber, monster.guid, (int)CreateFishManager.Instance.currGameType.currSitData.consumeGoldNum);
}
+255 -105
View File
@@ -15,6 +15,7 @@ using Assets.MyGame.Scripts.Net;
using Assets.MyGame.Scripts.Net.API;
using Assets.MyGame.Scripts.Net.API.GameConfig_SubClass;
using Assets.MyGame.Scripts.Net.APIResponses.Enum;
using Assets.MyGame.Scripts.Net.APIResponses.GameConfig_SubClass;
using Assets.MyGame.Scripts.Net.WebResponses;
using cfg;
using Newtonsoft.Json;
@@ -22,11 +23,11 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TMPro;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using static UnityEditor.FilePathAttribute;
using Random = UnityEngine.Random;
/// <summary>
@@ -58,7 +59,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>fishArrayNumber → FishArrayConfig(鱼阵配置缓存)</summary>
private Dictionary<string, FishArrayConfig> fishArrayConfigDic;
/// <summary>fishNumber → FishTypeConfig(与 fishDatas 相同来源,供内部高频使用)</summary>
/// <summary>fishNumber → FishTypeConfig(与 fishDatas 相同来源,供内部使用)</summary>
private Dictionary<string, FishTypeConfig> fishTypeConfigDic;
// ----------------------------------------------------------------
@@ -66,10 +67,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ----------------------------------------------------------------
/// <summary>全部存活鱼(包含 Boss / 小鱼 / 黄金鱼)</summary>
public Dictionary<string, MonsterContral> fishDatas_hashCodekey = new Dictionary<string, MonsterContral>();
public Dictionary<string, MonsterContral> fishDatas_hashCodekey = new Dictionary<string, MonsterContral>();
/// <summary>Boss 鱼</summary>
public Dictionary<string, MonsterContral> fishDatas_hashCodekey_Boss = new Dictionary<string, MonsterContral>();
public Dictionary<string, MonsterContral> fishDatas_hashCodekey_Boss = new Dictionary<string, MonsterContral>();
/// <summary>普通 / 黄金 / 特殊鱼(非 Boss)</summary>
public Dictionary<string, MonsterContral> fishDatas_hashCodekey_Small = new Dictionary<string, MonsterContral>();
@@ -96,6 +97,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>鱼的父节点(保持场景层级整洁)</summary>
public Transform fishRoot;
/// <summary>鱼的父节点(保持场景层级整洁)</summary>
public Transform poolRoot;
/// <summary>当前房间可生成鱼列表(与 NativeArray 下标对齐)</summary>
public List<RoomFishDetailConfig> spawnList;
@@ -110,28 +113,32 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>arrayNumber → 该阵型所有可用生成配置</summary>
private Dictionary<string, List<RoomFishDetailConfig>> yz_FishConfig_Line;
/// <summary>列表下标 → arrayNumber(用于随机取阵型)</summary>
private Dictionary<int, string> yz_FishConfig_Line_Dic;
private Dictionary<int, string> yz_FishConfig_Line_Dic;
/// <summary>arrayNumber → 列表下标(反向索引)</summary>
private Dictionary<string, int> yz_FishConfig_Line_Dic1;
private Dictionary<string, int> yz_FishConfig_Line_Dic1;
/// <summary>二维列表,与字典保持同步(供随机无重复取阵型用)</summary>
private List<List<RoomFishDetailConfig>> yz_FishConfig_Line_List;
private List<List<RoomFishDetailConfig>> yz_FishConfig_Line_List;
// ------ Job System NativeArray ------
private NativeArray<float> timers; // 每条鱼的累计计时
private NativeArray<float> frequencies; // 每条鱼的生成间隔
private NativeArray<int> shouldSpawn; // 1=本帧应尝试生成,0=冷却中
private NativeArray<int> shouldSpawn; // 1=本帧应尝试生成,0=冷却中
// ------ 各类计时器 ------
private float bossTimer = 1f; // Boss 刷新倒计时(秒)
private float yzTimer; // 鱼阵刷新倒计时(秒)
private float ptTimer = 3f; // 普通鱼批量启用倒计时(秒)
private int yzCount; // 本轮同时激活阵型数量
private int ptCount; // 本轮同时启用普通鱼数量
private int yz_LineCount = 0; // 场景内鱼阵路线总数
private RoomFishProbabilityConfig bossCreateData; // Boss 创建数据
private float bossTimer = 999f; // Boss 刷新倒计时(秒)
private RoomFishProbabilityConfig yzCreateData; // 鱼阵创建数据
private float yzTimer=999f; // 鱼阵刷新倒计时(秒)
private RoomFishProbabilityConfig ptCreateData; // 普通鱼创建数据
private float ptTimer = 999f; // 普通鱼批量启用倒计时(秒)
private int yzCount; // 本轮同时激活阵型数量
private int ptCount; // 本轮同时启用普通鱼数量
private int bossCount; // 本轮同时启用Boss鱼数量
private int yz_LineCount = 0; // 场景内鱼阵路线总数
/// <summary>是否开启放鱼(false 时 Update 不执行生成逻辑)</summary>
public bool fangzhu;
public bool isResources=false;
// ================================================================
// 懒加载属性
// ================================================================
@@ -180,17 +187,28 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// 确保 FishRoot 存在
if (fishRoot == null)
fishRoot = new GameObject("FishRoot").transform;
if (poolRoot == null)
fishRoot = new GameObject("poolRoot").transform;
// 监听服务器下发的创鱼事件
EventCenter.Instance.AddEventListener<SyncGameData>(
ConstEventString.SyncGameData_CreateFish, CreateFish);
// 随机初始化计时器,避免所有类型同帧触发
yzTimer = Random.Range(2f, 6f);
yzCount = Random.Range(2, 5);
ptCount = Random.Range(1, 4);
}
}
public void InitChuYu()
{
// 随机初始化计时器,避免所有类型同帧触发
yzCount = Random.Range(yzCreateData.countRange[0], yzCreateData.countRange[1]);
ptCount = Random.Range(ptCreateData.countRange[0], ptCreateData.countRange[1]);
bossCount = Random.Range(ptCreateData.countRange[0], ptCreateData.countRange[1]);
yzTimer = 0.5f ;
ptTimer =0.5f ;
bossTimer = 5f;
//yzTimer = Random.Range(yzCreateData.timeRange[0], yzCreateData.timeRange[1]);
//ptTimer = Random.Range(ptCreateData.timeRange[0], ptCreateData.timeRange[1]);
//bossTimer = Random.Range(bossCreateData.timeRange[0], bossCreateData.timeRange[1]);
}
private void OnDestroy()
{
EventCenter.Instance.RemoveEventListener<SyncGameData>(
@@ -206,6 +224,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
private void Update()
{
if (!isResources)
{
return;
}
// 未初始化 或 未开启放鱼 → 跳过
if (spawnList == null || !fangzhu) return;
@@ -214,8 +236,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ---- 1. 用 Job System 并行更新所有鱼的计时器 ----
var job = new FishSpawnTimerJob
{
deltaTime = dt,
timers = timers,
deltaTime = dt,
timers = timers,
frequencies = frequencies,
shouldSpawn = shouldSpawn,
};
@@ -244,11 +266,17 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
bossTimer -= dt;
if (bossTimer > 0f) return;
bossTimer = 25f;
bossTimer = Random.Range(bossCreateData.timeRange[0], bossCreateData.timeRange[1]);
if (!fishTypeConfig.TryGetValue(FishTypeEnum.Boss鱼, out var bossList) || bossList.Count == 0)
return;
//foreach (var item in bossList)
//{
// if (item.fishNumber == 13027.ToString())
// {
// item.isCreate = 2;
// }
//}
bossList[Random.Range(0, bossList.Count)].isCreate = 2;
}
@@ -258,8 +286,11 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
yzTimer -= dt;
if (yzTimer > 0f) return;
yzTimer = Random.Range(1f, 3f);
yzCount = Random.Range(2, 5);
yzCount = Random.Range(yzCreateData.countRange[0], yzCreateData.countRange[1]);
yzTimer = Random.Range(yzCreateData.timeRange[0], yzCreateData.timeRange[1]);
int lineCount = yz_FishConfig_Line_List.Count;
if (lineCount == 0) return;
@@ -290,8 +321,11 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
ptTimer -= dt;
if (ptTimer > 0f) return;
ptTimer = 3f;
ptCount = Random.Range(1, 4);
ptCount = Random.Range(ptCreateData.countRange[0], ptCreateData.countRange[1]);
ptTimer = Random.Range(ptCreateData.timeRange[0], ptCreateData.timeRange[1]);
if (!fishTypeConfig.TryGetValue(FishTypeEnum.普通鱼, out var normalList) || normalList.Count == 0)
return;
@@ -349,14 +383,14 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
var sgd = new SyncGameData
{
sitPos = GameManager.Instance.gameData.roomJoinNotice.position,
sitPos = GameManager.Instance.gameData.roomJoinNotice.position,
frameType = FrameDataType.createFish,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
frameData = new FrameData_CreateFish
{
fishNumber = fish.fishNumber,
guid = Guid.NewGuid().ToString(),
moveLineId = pathId.ToString()
fishNumber = fish.fishNumber,
guid = Guid.NewGuid().ToString(),
moveLineId = pathId.ToString()
}
};
@@ -376,7 +410,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
FishYZ.Init();
roomFishConfig = new Dictionary<GameTypeEnum, RoomFishConfig>();
createDic = new Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>>();
createDic = new Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>>();
var list = GameManager.Instance.gameConfig.roomFishConfigs;
if (list == null || list.Count == 0) return;
@@ -419,18 +453,18 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>
/// 进入房间时初始化生成系统:加载当前房间配置、分配 NativeArray。
/// </summary>
public void InitSpawnSystem(GameTypeEnum gameType)
public async void InitSpawnSystem(GameTypeEnum gameType)
{
EnsureInit();
// 初始化分类容器
fishTypeConfig = new Dictionary<FishTypeEnum, List<RoomFishDetailConfig>>();
yz_FishConfig_Line = new Dictionary<string, List<RoomFishDetailConfig>>();
fishTypeConfig = new Dictionary<FishTypeEnum, List<RoomFishDetailConfig>>();
yz_FishConfig_Line = new Dictionary<string, List<RoomFishDetailConfig>>();
yz_FishConfig_Line_Dic = new Dictionary<int, string>();
yz_FishConfig_Line_Dic1= new Dictionary<string, int>();
yz_FishConfig_Line_List= new List<List<RoomFishDetailConfig>>();
spawnList = new List<RoomFishDetailConfig>();
spawnDic = new Dictionary<string, RoomFishDetailConfig>();
yz_FishConfig_Line_Dic1 = new Dictionary<string, int>();
yz_FishConfig_Line_List = new List<List<RoomFishDetailConfig>>();
spawnList = new List<RoomFishDetailConfig>();
spawnDic = new Dictionary<string, RoomFishDetailConfig>();
var config = RoomFishConfig[gameType];
@@ -459,10 +493,42 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
int currRoomLevel = GameManager.Instance.gameData.currRoomData.roomLevel;
if (config.roomFishLevelList != null)
{
foreach (var item in config.roomFishProbabilityList)
{
if (item.roomLevel != currRoomLevel) continue;
switch (item.type)
{
case 1:
switch ((FishTypeEnum)item.fishType)
{
case FishTypeEnum.普通鱼:
ptCreateData = item;
break;
case FishTypeEnum.Boss鱼:
bossCreateData = item;
break;
case FishTypeEnum.黄金鱼:
break;
case FishTypeEnum.特殊鱼:
break;
default:
break;
}
break;
case 2:
//yzTimer=item.
yzCreateData = item;
break;
default:
break;
}
}
foreach (var item in config.roomFishLevelList)
{
if (item.roomLevel != currRoomLevel) continue;
if (item.type == 2)
{
spawnDic[item.fishNumber] = item;
@@ -482,13 +548,13 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ---- 分配 Job System NativeArray ----
int count = spawnList.Count;
DisposeNativeArrays(); // 防止重复进房泄漏
timers = new NativeArray<float>(count, Allocator.Persistent);
timers = new NativeArray<float>(count, Allocator.Persistent);
frequencies = new NativeArray<float>(count, Allocator.Persistent);
shouldSpawn = new NativeArray<int>(count, Allocator.Persistent);
shouldSpawn = new NativeArray<int>(count, Allocator.Persistent);
for (int i = 0; i < count; i++)
{
timers[i] = 0f;
timers[i] = 0f;
frequencies[i] = spawnList[i].fishFrequency;
shouldSpawn[i] = 1; // 初始全部允许生成
}
@@ -500,6 +566,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
if (key.StartsWith("鱼阵"))
yz_LineCount++;
}
InitChuYu();
}
/// <summary>
@@ -529,7 +596,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
yz_FishConfig_Line_List.Add(new List<RoomFishDetailConfig>());
int newIdx = yz_FishConfig_Line_List.Count - 1;
yz_FishConfig_Line_Dic[newIdx] = yz.arrayNumber;
yz_FishConfig_Line_Dic[newIdx] = yz.arrayNumber;
yz_FishConfig_Line_Dic1[yz.arrayNumber] = newIdx;
}
@@ -540,23 +607,35 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>
/// 关闭生成系统:清理列表,销毁场景内所有鱼对象。
/// </summary>
public void CloseSpawnSystem()
public async void CloseSpawnSystem()
{
//await Task.Delay(2000);
spawnList = null;
spawnDic = null;
yz_FishConfig_Line_Dic = null;
yz_FishConfig_Line = null;
yz_FishConfig_Line_Dic1 = null;
if (fishRoot == null) return;
foreach (var item in fishDatas_hashCodekey)
{
if (item.Value.gameObject!=null)
{
Destroy(item.Value.gameObject);
for (int i = fishRoot.childCount - 1; i >= 0; i--)
Destroy(fishRoot.GetChild(i).gameObject);
}
}
fishDatas_hashCodekey.Clear();
fishDatas_hashCodekey_Boss.Clear();
fishDatas_hashCodekey_Small.Clear();
//for (int i = fishDatas_hashCodekey.childCount - 1; i >= 0; i--)
// Destroy(fishRoot.GetChild(i).gameObject);
}
/// <summary>释放 NativeArray(避免 Unity 内存泄漏警告)。</summary>
private void DisposeNativeArrays()
{
if (timers.IsCreated) timers.Dispose();
if (timers.IsCreated) timers.Dispose();
if (frequencies.IsCreated) frequencies.Dispose();
if (shouldSpawn.IsCreated) shouldSpawn.Dispose();
}
@@ -604,16 +683,27 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// 网络回调:创建鱼
// ================================================================
///// <summary>
///// 收到服务器 SyncGameData 创鱼事件,反序列化并执行实例化。
///// </summary>
//public void CreateFish(SyncGameData syncGameData)
//{
// var rotateData = JsonConvert.DeserializeObject<FrameData_CreateFish>(
// syncGameData.frameData.ToString());
// SpawnFishMainThread(rotateData, syncGameData.time);
//}
/// <summary>
/// 收到服务器 SyncGameData 创鱼事件,反序列化并执行实例化。
/// AI优化过的
/// </summary>
/// <param name="syncGameData"></param>
public void CreateFish(SyncGameData syncGameData)
{
var rotateData = JsonConvert.DeserializeObject<FrameData_CreateFish>(
syncGameData.frameData.ToString());
SpawnFishMainThread(rotateData, syncGameData.time);
var rotateData = FrameDataParser.Parse<FrameData_CreateFish>(syncGameData.frameData);
if (rotateData != null)
SpawnFishMainThread(rotateData, syncGameData.time);
}
/// <summary>
/// 主线程实例化鱼对象(单体鱼 / 鱼阵分发)。
/// </summary>
@@ -655,19 +745,30 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
//var prefab = FishResourcesData.GetFishPrefab(int.Parse(fishType.fishNumber));
//var fish = Instantiate(prefab, new Vector3(9999, 9999, 0), prefab.transform.rotation, fishRoot);
var fish = Pool.Instance.Get(int.Parse(createFishData.fishNumber), new Vector3(9999, 9999, 0), Quaternion.identity,fishRoot);
try
{
var fish = Pool.Instance.Get(int.Parse(createFishData.fishNumber), new Vector3(9999, 9999, 0), Quaternion.identity, fishRoot);
var mc = fish.GetComponent<MonsterContral>() ?? fish.AddComponent<MonsterContral>();
mc.monsterData.fishTypeConfig = FishDatas[createFishData.fishNumber];
mc.guid = createFishData.guid;
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
mc.fishenum=(FishTypeEnum) fishType.fishType;
// 按鱼类型放入对应字典
RegisterFishInstance(mc, fishType.fishType);
var mc = fish.GetComponent<MonsterContral>() ?? fish.AddComponent<MonsterContral>();
mc.monsterData.fishTypeConfig = FishDatas[createFishData.fishNumber];
mc.guid = createFishData.guid;
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
mc.Init(createFishData.moveLineId, spawnDic[createFishData.fishNumber].times);
// 按鱼类型放入对应字典
RegisterFishInstance(mc, fishType.fishType);
Debug.Log($"[CreateFishManager] 生成鱼:{fishType.fishName}");
}
catch (Exception ex)
{
mc.Init(createFishData.moveLineId, spawnDic[createFishData.fishNumber].times);
Debug.LogError(createFishData.fishNumber);
Debug.LogError(ex.Message);
}
Debug.Log($"[CreateFishManager] 生成鱼:{fishType.fishName}");
return true;
}
@@ -707,8 +808,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
return;
}
var prefab = FishResourcesData.GetFishPrefab(int.Parse(fishType.fishNumber));
var pos = new Vector3(9999, 9999, 0);
var prefab = FishResourcesData.GetFishPrefab(int.Parse(fishType.fishNumber));
var pos = new Vector3(9999, 9999, 0);
if (!FishYZ.dicfishYZ.TryGetValue(yz.arrayNumber, out var pathList) || pathList.Count == 0)
{
@@ -761,6 +862,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
{
foreach (int pathId in pathList)
{
if (!isResources)
{
yield break;
}
ShanXing(createFishData, yz, pos, prefab, pathId, count, time);
yield return new WaitForSeconds(0.8f);
}
@@ -777,19 +882,19 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
for (int i = 1; i <= 16; i++)
{
// 交替正负角度,形成扇形分布
float angle = i * 5f * (i % 2 == 0 ? -1f : 1f);
float angle = i * 5f * (i % 2 == 0 ? -1f : 1f);
var rotation = Quaternion.Euler(
prefab.transform.eulerAngles + Vector3.forward * angle);
//var fish = Instantiate(prefab, pos, rotation, fishRoot);
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, rotation, fishRoot);
var mc = fish.GetComponent<MonsterContral>();
var mc = fish.GetComponent<MonsterContral>();
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
mc.guid = createFishData.guid + i;
mc.guid = createFishData.guid + i;
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
fishDatas_hashCodekey[mc.guid] = mc;
//mc.fishenum = (FishTypeEnum)fishType.fishType;
fishDatas_hashCodekey[mc.guid] = mc;
fishDatas_hashCodekey_Small[mc.guid] = mc;
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
@@ -807,20 +912,20 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
for (int i = 0; i < count; i++)
{
float angle = (360f / count) * i;
float angle = (360f / count) * i;
var rotation = Quaternion.Euler(
prefab.transform.eulerAngles + Vector3.forward * angle);
//var fish = Instantiate(prefab, pos, rotation, fishRoot);
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, rotation, fishRoot);
var mc = fish.GetComponent<MonsterContral>();
var mc = fish.GetComponent<MonsterContral>();
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
mc.guid = createFishData.guid + i;
mc.guid = createFishData.guid + i;
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
fishDatas_hashCodekey[mc.guid] = mc;
fishDatas_hashCodekey[mc.guid] = mc;
fishDatas_hashCodekey_Small[mc.guid] = mc;
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
@@ -837,17 +942,21 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
for (int i = 0; i < count; i++)
{
if (!isResources)
{
yield break;
}
//var fish = Instantiate(prefab, pos, prefab.transform.rotation, fishRoot);
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, Quaternion.identity, fishRoot);
var mc = fish.GetComponent<MonsterContral>() ?? fish.AddComponent<MonsterContral>();
var mc = fish.GetComponent<MonsterContral>() ?? fish.AddComponent<MonsterContral>();
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
mc.guid = createFishData.guid + i;
mc.guid = createFishData.guid + i;
// 每条鱼额外减去已等待秒数,使路径起点与帧数同步
mc.moveTime = ((BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f) - i;
fishDatas_hashCodekey[mc.guid] = mc;
fishDatas_hashCodekey[mc.guid] = mc;
fishDatas_hashCodekey_Small[mc.guid] = mc;
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
@@ -874,7 +983,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
count = Mathf.Min(count, max - min); // 不能超过范围
var result = new HashSet<int>();
var rand = new System.Random();
var rand = new System.Random();
while (result.Count < count)
result.Add(rand.Next(min, max));
@@ -893,8 +1002,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
count = Mathf.Min(count, max - min);
var keyList = keyCollection.ToList();
var indices = new HashSet<int>();
var rand = new System.Random();
var result = new List<string>(count);
var rand = new System.Random();
var result = new List<string>(count);
while (indices.Count < count)
{
@@ -916,7 +1025,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
public List<string> SyncGameData_SendRendromDieFishID(
int count, List<RedPacketRecord> coinNum, Vector3 v3Point)
{
var guids = new List<string>(count);
var guids = new List<string>(count);
var tempKeys = fishDatas_hashCodekey_Small.Keys.ToList();
// 若存活鱼不足 count,全部选取
@@ -937,17 +1046,17 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
int posID = currGameType.currSitData.posID;
var sgd = new SyncGameData
{
sitPos = posID,
sitPos = posID,
frameType = FrameDataType.randomDieFish,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
frameData = new FrameData_RandomDieFish
{
x = v3Point.x,
y = v3Point.y,
z = v3Point.z,
guids = guids,
x = v3Point.x,
y = v3Point.y,
z = v3Point.z,
guids = guids,
coinNum = coinNum,
count = count
count = count
}
};
@@ -956,13 +1065,13 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
}
/// <summary>
/// 按 ID 杀死一条鱼(无特效版)。
/// 鱼离场
/// </summary>
public void Id_DieFish_NotFX(string fishId)
{
if (!fishDatas_hashCodekey.TryGetValue(fishId, out var monster)) return;
Pool.Instance.Return(monster.gameObject);
monster.DieFish();
fishDatas_hashCodekey.Remove(fishId);
}
@@ -992,18 +1101,18 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
monster.transform.position,
UIManager.Instance.uiRoot.GetComponent<Canvas>());
var coinScript = award.GetComponent<CoinScript>();
var endTra = new GameObject("CoinEndPoint").transform;
endTra.position = v3Point;
endTra.parent = coinScript.transform;
var coinScript = award.GetComponent<CoinScript>();
var endTra = new GameObject("CoinEndPoint").transform;
endTra.position = v3Point;
endTra.parent = coinScript.transform;
coinScript.endPoint = endTra;
coinScript.isBoss = true;
coinScript.isBoss = true;
coinScript.SetCoinCount(coinNum.Amount);
}
MonsterDieList.Instance.SmallHuangYiHuang(
monster.transform.position,
monster.monsterData.fishTypeConfig.fishNumber, 1000);
//MonsterDieList.Instance.SmallHuangYiHuang(
// monster.transform.position,
// monster.monsterData.fishTypeConfig.fishNumber, 1000);
monster.DieFish();
fishDatas_hashCodekey.Remove(fishId);
@@ -1017,7 +1126,25 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
for (int i = 0; i < ids.Count; i++)
Id_DieFish_FX(ids[i], coinNum[i], v3Point);
}
public void DieFishList(string guid)
{
fishDatas_hashCodekey.Remove(guid);
if (fishDatas_hashCodekey_Boss.ContainsKey(guid))
{
fishDatas_hashCodekey_Boss.Remove(guid);
}
if (fishDatas_hashCodekey_Small.ContainsKey(guid))
{
fishDatas_hashCodekey_Small.Remove(guid);
}
}
/// <summary>
/// 收到服务器 WebSocket 杀鱼通知,处理金币加分、特效、音效。
/// </summary>
@@ -1027,7 +1154,15 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
.arguments[0];
Debug.Log($"[CreateFishManager] 杀鱼延迟:{DateTimeOffset.Now.ToUnixTimeSeconds() - killFish.timespan}s");
foreach (var item in currGameType.list_Sits)
{
if (item.user==killFish.userId)
{
item.monCotl_Lock=null;
//item.lockFX.gameObject.SetActive(false);
}
}
if (!fishDatas_hashCodekey.TryGetValue(killFish.fishId, out var monster)) return;
// 加分回调(在金币飞完后执行)
@@ -1062,16 +1197,31 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
monster.transform.position,
UIManager.Instance.uiRoot.GetComponent<Canvas>());
var coinScript = award.GetComponent<CoinScript>();
coinScript.endPoint = currGameType.currSitData.transform;
coinScript.isBoss = false;
var coinScript = award.GetComponent<CoinScript>();
foreach (var item in currGameType.list_Sits)
{
if (killFish.userId==item.user)
{
coinScript.endPoint = item.transform;
}
}
coinScript.isBoss = false;
coinScript.SetCoinCount(killFish.gold);
coinScript.JiaFen = onScoreAdd;
coinScript.JiaFen = onScoreAdd;
}
else
{
// Boss 鱼:显示浮动分数文本
var bossCtrl = (MonsterControl_BossBase)monster;
foreach (var item in currGameType.list_Sits)
{
if (killFish.userId == item.user)
{
bossCtrl.v3 = item.transform.position;
}
}
bossCtrl.tMP_CurrBossScore = Instantiate(
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAwardTmp,
currGameType.subPanelParent.parent)
@@ -1,4 +1,5 @@
using System;
using Assets.MyGame.Scripts.Net.APIResponses.GameConfig_SubClass;
using System;
using System.Collections.Generic;
namespace Assets.MyGame.Scripts.Net.API.GameConfig_SubClass
@@ -26,6 +27,11 @@ namespace Assets.MyGame.Scripts.Net.API.GameConfig_SubClass
/// 按房间等级出鱼配置
/// </summary>
public List<RoomFishLevelConfig> roomFishLevelList;
/// <summary>
/// 出鱼概率配置
/// </summary>
public List<RoomFishProbabilityConfig> roomFishProbabilityList= new List<RoomFishProbabilityConfig>();
}
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assets.MyGame.Scripts.Net.APIResponses.GameConfig_SubClass
{
[Serializable]
public class RoomFishProbabilityConfig
{
public int roomLevel = 0;
public int type = 0;
public int fishType;
public List<int> firstFishCountRange;
public List<int> timeRange ;
public List<int> countRange;
public List<int> maxCountRange;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 36d2691ff5a725b4a8b961d7bb54e1eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -10,6 +10,34 @@ using UnityEngine;
namespace Assets.MyGame.Scripts.Net.WebResponses
{
public static class FrameDataParser
{
public static T Parse<T>(object frameData) where T : class, new()
{
if (frameData == null) return null;
// 如果已经是目标类型,直接返回
if (frameData is T typed) return typed;
// 如果是字符串,直接反序列化
if (frameData is string str)
return JsonConvert.DeserializeObject<T>(str);
// 如果是 JObject,轻量解析
if (frameData is JObject jObj)
return jObj.ToObject<T>();
// 兜底:调用 ToString 再反序列化
return JsonConvert.DeserializeObject<T>(frameData.ToString());
}
}
[Serializable]
public enum FrameDataType
{
@@ -65,6 +93,7 @@ namespace Assets.MyGame.Scripts.Net.WebResponses
public class FrameData_ChangeAutoTarget : FrameData
{
public string targetGuid;
public string targetPostName;
}
[Serializable]
public class FrameData_RandomDieFish : FrameData
@@ -210,6 +210,11 @@ namespace Assets.MyGame.Scripts.Net
case GameType.FLZY:
{
var panel = UIManager.Instance.Get<GameMainPanel_FLZY>(UIPanel.MainGamePanelFLZY);
if (panel.currSitData.user== userid)
{
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelFLZY);
break;
}
foreach (var item in panel.list_Sits)
{
if (item.user == userid)
@@ -238,6 +243,11 @@ namespace Assets.MyGame.Scripts.Net
case GameType.XJMH:
{
var panel = UIManager.Instance.Get<GameMainPanel_XJMH>(UIPanel.MainGamePanelXJMH);
if (panel.currSitData.user == userid)
{
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelXJMH);
break;
}
foreach (var item in panel.list_Sits)
{
Debug.Log(item.user+"---"+ userid);
@@ -252,6 +262,11 @@ namespace Assets.MyGame.Scripts.Net
case GameType.HHWK:
{
var panel = UIManager.Instance.Get<GameMainPanel_HHWK>(UIPanel.MainGamePanelHHWK);
if (panel.currSitData.user == userid)
{
UIManager.Instance.ShowAsync(UIPanel.HomeMainPanel, UIPanel.MainGamePanelHHWK);
break;
}
foreach (var item in panel.list_Sits)
{
if (item.user == userid)
@@ -5,6 +5,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
@@ -17,6 +18,10 @@ public class SitPosData : MonoBehaviour
[Header("金币")]
public TextMeshProUGUI tMP_TurretConsumeNum;
public TextMeshProUGUI tMP_GoldNum;
public Button btn_TurretAdd;
public Button btn_TurretMinus;
public long goldNum;
public long consumeGoldNum;
[Header("炮台")]
@@ -27,6 +32,7 @@ public class SitPosData : MonoBehaviour
public TurretData currentTurret;
[Header("锁定")]
public MonsterContral monCotl_Lock;
public Transform monCotl_Lock_Position;
public bool isLock=false;
public GameObject lockFX;
@@ -45,6 +51,15 @@ public class SitPosData : MonoBehaviour
// return td1.turretID.CompareTo(td2.turretLevel);
//});
dic_Turrets = list_Turrets.ToDictionary(td => td.turretID);
btn_TurretAdd.onClick.AddListener(() =>
{
ChangeTurretAddConsumeNum(1000);
});
btn_TurretMinus.onClick.AddListener(() =>
{
ChangeTurretMinusConsumeNum(1000);
});
}
public void Update()
{
@@ -83,6 +98,18 @@ public class SitPosData : MonoBehaviour
consumeGoldNum = n;
tMP_TurretConsumeNum.text = consumeGoldNum.ToString();
}
public void ChangeTurretAddConsumeNum(int n = 0)
{
consumeGoldNum += n;
tMP_TurretConsumeNum.text = consumeGoldNum.ToString();
}
public void ChangeTurretMinusConsumeNum(int n = 0)
{
consumeGoldNum -= n;
tMP_TurretConsumeNum.text = consumeGoldNum.ToString();
}
public bool ConsumeGold(int bl=1)
{
@@ -3,9 +3,11 @@ using Spine.Unity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.InputSystem;
using UnityEngine.ResourceManagement.AsyncOperations;
using static UnityEngine.AddressableAssets.Addressables;
[Serializable]
@@ -40,9 +42,9 @@ public class AudioResourcesData
await Addressables.LoadAssetsAsync<AudioClip>(keys, audio =>
{
Debug.Log("加载音频: " + audio.name);
Debug.Log("加载音频ID: " + name_IDDic[audio.name]);
if (name_IDDic.ContainsKey(audio.name))
{
Debug.Log("加载音频ID: " + name_IDDic[audio.name]);
audioClipDefaultDic.Add(name_IDDic[audio.name],audio);
}
}, MergeMode.Intersection).Task;
@@ -52,7 +54,7 @@ public class AudioResourcesData
}
Debug.Log("加载了:"+ audioClipDic.Count);
}
public static async void LoadAudioGame()
public static async Task LoadAudioGame()
{
GameType gameType=GameManager.Instance.gameData.currGameType;
var keys = new List<string> { Audio_AALabel, gameType.ToString() };
@@ -62,16 +64,52 @@ public class AudioResourcesData
//Debug.Log("加载音频ID: " + name_IDDic[audio.name]);
if (name_IDDic.ContainsKey(audio.name))
{
audioClipGameDic.Add(name_IDDic[audio.name], audio);
audioClipGameDic[name_IDDic[audio.name]]= audio;
}
}, MergeMode.Intersection).Task;
audioClipDic=new Dictionary<int, AudioClip>(audioClipDefaultDic);
foreach (var item in audioClipGameDic)
{
audioClipDic.Add(item.Key,item.Value);
audioClipDic[item.Key]=item.Value;
}
Debug.Log("加载了:"+ audioClipDic.Count);
}
public static async Task UnLoadAudioGame()
{
GameType gameType = GameManager.Instance.gameData.currGameType;
var keys = new List<string> { Audio_AALabel, gameType.ToString() };
// 加载对应的句柄(只是为了拿到引用,之后释放)
AsyncOperationHandle<IList<AudioClip>> handle = Addressables.LoadAssetsAsync<AudioClip>(keys, null, MergeMode.Intersection);
await handle.Task;
// 遍历卸载对应的音频
foreach (var audio in handle.Result)
{
if (name_IDDic.ContainsKey(audio.name))
{
int id = name_IDDic[audio.name];
if (audioClipGameDic.ContainsKey(id))
{
audioClipGameDic.Remove(id);
Debug.Log($"卸载音频: {audio.name} (ID={id})");
}
}
}
// 释放 Addressables 资源句柄
Addressables.Release(handle);
// 重建总字典:保留默认音频 + 剩余游戏音频
audioClipDic = new Dictionary<int, AudioClip>(audioClipDefaultDic);
foreach (var item in audioClipGameDic)
{
audioClipDic[item.Key] = item.Value;
}
Debug.Log("卸载完成,当前音频数量:" + audioClipDic.Count);
}
}
@@ -3,6 +3,7 @@ using Spine.Unity;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using static UnityEngine.AddressableAssets.Addressables;
@@ -39,22 +40,27 @@ public class FishResourcesData
private static Dictionary<string,int> FishResourcesPrefabsDic ;//prefabpath--id
private static Dictionary<string,int> FishResourcesSpineDieDic ;//dieSpinepath--id
private static Dictionary<string,int> FishResourcesSpriteDic;//Spritepath--id
static FishResourcesData()
static FishResourcesData()
{
Init();
}
async static void Init()
{
string prefabFishPath = Resources.Load<TextAsset>("tbfishresources").text;
var v = JsonConvert.DeserializeObject<List<FishResourcesData>>(prefabFishPath);
FishResourcesPrefabsDic=new Dictionary<string, int>();
FishResourcesPrefabsDic = new Dictionary<string, int>();
fishResourcesDatasDic = new Dictionary<int, FishResourcesData>();
FishResourcesSpineDieDic = new Dictionary<string, int>();
FishResourcesSpriteDic = new Dictionary<string, int>();
foreach (var item in v)
{
if (item.prefabFishResourcesPath!=null&& item.prefabFishResourcesPath != "")
if (item.prefabFishResourcesPath != null && item.prefabFishResourcesPath != "")
{
Debug.Log($"添加鱼资源数据: {item.fishNumber} - {item.prefabFishResourcesPath}");
FishResourcesPrefabsDic.Add(item.prefabFishResourcesPath, item.fishNumber);
FishResourcesSpriteDic.Add(item.prefabFishResourcesPath, item.fishNumber);
if (item.dieEffectAssets!=null&&item.dieEffectAssets!="")
if (item.dieEffectAssets != null && item.dieEffectAssets != "")
{
FishResourcesSpineDieDic.Add(item.dieEffectAssets, item.fishNumber);
}
@@ -65,7 +71,6 @@ public class FishResourcesData
}
}
}
private static Dictionary<int, GameObject> fishPrefabDic;//id--prefabs
@@ -73,48 +78,145 @@ public class FishResourcesData
public static Dictionary<int, Sprite> fishResourcesSpritesDic;//id--Sprite
private static Dictionary<int, SkeletonDataAsset> diePrefabDic;//id--SkeletonDataAsset
public static async void LoadFishAssetsData()
public static async Task LoadFishAssetsData()
{
// 清空对象池,避免残留
Pool.Instance.Clear();
if (fishPrefabDic != null)
return;
fishPrefabDic = new Dictionary<int, GameObject>();
diePrefabDic= new Dictionary<int, SkeletonDataAsset>();
diePrefabDic = new Dictionary<int, SkeletonDataAsset>();
fishResourcesSpritesDic = new Dictionary<int, Sprite>();
// ---------------- Prefab ----------------
var keys = new List<string> { prefabFish_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
await Addressables.LoadAssetsAsync<GameObject>(keys, prefab =>
var prefabHandle = Addressables.LoadAssetsAsync<GameObject>(keys, prefab =>
{
if (FishResourcesPrefabsDic.ContainsKey(prefab.name))
if (FishResourcesPrefabsDic.TryGetValue(prefab.name, out int id))
{
fishPrefabDic.Add(FishResourcesPrefabsDic[prefab.name], prefab);
prefab.GetComponent<MonsterContral>().fishTypeID = FishResourcesPrefabsDic[prefab.name];
// 防御性检查,避免重复覆盖
if (fishPrefabDic.ContainsKey(id))
Debug.LogWarning($"Prefab重复加载,覆盖ID={id}, 名称={prefab.name}");
Pool.Instance.dic.Add(FishResourcesPrefabsDic[prefab.name], new PoolData(prefab,CreateFishManager.Instance.fishRoot.gameObject));
fishPrefabDic[id] = prefab;
// 防御性检查组件
var mc = prefab.GetComponent<MonsterContral>();
if (mc != null)
mc.fishTypeID = id;
// 加入对象池
Pool.Instance.dic[id] = new PoolData(prefab, CreateFishManager.Instance.poolRoot.gameObject, id);
}
}, MergeMode.Intersection).Task;
}, MergeMode.Intersection);
await prefabHandle.Task;
Addressables.Release(prefabHandle);
Debug.Log($"加载完成,共 {fishPrefabDic.Count} 个鱼Prefab");
keys = new List<string> {dieSpine_AALabel,/* GameManager.Instance.gameData.currGameType.ToString()*/GameManager.Instance.gameData.currGameType.ToString() };
await Addressables.LoadAssetsAsync<SkeletonDataAsset>(keys, data =>
// ---------------- 死亡 Spine 动效 ----------------
keys = new List<string> { dieSpine_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
var dieHandle = Addressables.LoadAssetsAsync<SkeletonDataAsset>(keys, data =>
{
if (FishResourcesSpineDieDic.ContainsKey(data.name))
if (FishResourcesSpineDieDic.TryGetValue(data.name, out int id))
{
diePrefabDic.Add(FishResourcesSpineDieDic[data.name], data); }
},MergeMode.Intersection).Task;
if (diePrefabDic.ContainsKey(id))
Debug.LogWarning($"死亡动效重复加载,覆盖ID={id}, 名称={data.name}");
diePrefabDic[id] = data;
}
}, MergeMode.Intersection);
await dieHandle.Task;
Addressables.Release(dieHandle);
Debug.Log($"加载完成,共 {diePrefabDic.Count} 个鱼死亡动效");
keys = new List<string> { Sprite_AALabel,/* GameManager.Instance.gameData.currGameType.ToString()*/GameManager.Instance.gameData.currGameType.ToString() };
await Addressables.LoadAssetsAsync<Sprite>(keys, data =>
// ---------------- 鱼 Sprite ----------------
keys = new List<string> { Sprite_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
var spriteHandle = Addressables.LoadAssetsAsync<Sprite>(keys, data =>
{
if (FishResourcesSpriteDic.ContainsKey(data.name))
if (FishResourcesSpriteDic.TryGetValue(data.name, out int id))
{
fishResourcesSpritesDic.Add(FishResourcesSpriteDic[data.name], data);
if (fishResourcesSpritesDic.ContainsKey(id))
Debug.LogWarning($"Sprite重复加载,覆盖ID={id}, 名称={data.name}");
fishResourcesSpritesDic[id] = data;
}
}, MergeMode.Intersection).Task;
}, MergeMode.Intersection);
await spriteHandle.Task;
Addressables.Release(spriteHandle);
Debug.Log($"加载完成,共 {fishResourcesSpritesDic.Count} 个鱼Sprite");
}
public static async Task UnLoadFishAssetsData()
{
Pool.Instance.Clear();
// 卸载 Prefab
var keys = new List<string> { prefabFish_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
var prefabHandle = Addressables.LoadAssetsAsync<GameObject>(keys, null, MergeMode.Intersection);
await prefabHandle.Task;
if (prefabHandle.Result != null)
{
foreach (var prefab in prefabHandle.Result)
{
if (FishResourcesPrefabsDic.TryGetValue(prefab.name, out int id))
{
if (fishPrefabDic.Remove(id))
{
Debug.Log($"卸载鱼Prefab: {prefab.name} (ID={id})");
}
}
}
}
Addressables.Release(prefabHandle);
// 卸载死亡 Spine 动效
keys = new List<string> { dieSpine_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
var dieHandle = Addressables.LoadAssetsAsync<SkeletonDataAsset>(keys, null, MergeMode.Intersection);
await dieHandle.Task;
if (dieHandle.Result != null)
{
foreach (var data in dieHandle.Result)
{
if (FishResourcesSpineDieDic.TryGetValue(data.name, out int id))
{
if (diePrefabDic.Remove(id))
{
Debug.Log($"卸载鱼死亡动效: {data.name} (ID={id})");
}
}
}
}
Addressables.Release(dieHandle);
// 卸载鱼 Sprite
keys = new List<string> { Sprite_AALabel, GameManager.Instance.gameData.currGameType.ToString() };
var spriteHandle = Addressables.LoadAssetsAsync<Sprite>(keys, null, MergeMode.Intersection);
await spriteHandle.Task;
if (spriteHandle.Result != null)
{
foreach (var sprite in spriteHandle.Result)
{
if (FishResourcesSpriteDic.TryGetValue(sprite.name, out int id))
{
if (fishResourcesSpritesDic.Remove(id))
{
Debug.Log($"卸载鱼Sprite: {sprite.name} (ID={id})");
}
}
}
}
Addressables.Release(spriteHandle);
Debug.Log($"卸载完成,剩余Prefab数量: {fishPrefabDic.Count}, 死亡动效数量: {diePrefabDic.Count}, Sprite数量: {fishResourcesSpritesDic.Count}");
}
public static GameObject GetFishPrefab(int fishNumber)
{
if (fishPrefabDic != null && fishPrefabDic.ContainsKey(fishNumber))