Files
5.24BuYu/Assets/MyGame/Scripts/Manager/CreateFishManager.cs
T
2026-03-18 17:26:14 +08:00

619 lines
21 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 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.WebResponses;
using cfg;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using Unity.Collections;
using Unity.Jobs;
using UnityEditor;
using UnityEngine;
using Random = UnityEngine.Random;
public class CreateFishManager : MonoSingleton<CreateFishManager>
{
#region //这里不用了 但是留着
/*public CreateFishData createFishData;
public async void InitCreateFishData(string path)
{
createFishData = await Addressables.LoadAssetAsync<CreateFishData>(path).Task;
}
public string path;*/
/// <summary>
/// 全局配置(外部初始化)
/// </summary>
//public GameConfig M_GameConfig { get { return GameManager.Instance.gameConfig; } }
#endregion
public GameConfig M_GameConfig => GameManager.Instance.gameConfig;
// 缓存字段
private Dictionary<GameTypeEnum, RoomFishConfig> roomFishConfig;
private Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>> createDic;
private Dictionary<string, FishTypeConfig> fishDatas;
public Dictionary<string,MonsterContral> fishDatas_hashCodekey=new Dictionary<string, MonsterContral>();
public Dictionary<string, FishTypeConfig> FishDatas { get {
if (fishDatas != null)
return fishDatas;
fishDatas =new Dictionary<string, FishTypeConfig>();
foreach (var item in M_GameConfig.fishTypeConfigs)
{
fishDatas.Add(item.fishNumber, item);
}
return fishDatas;
} }
#region 初始化鱼生成配置
/// <summary>
/// 懒加载初始化(只执行一次)
/// </summary>
private void EnsureInit()
{
if (roomFishConfig != null)
return;
FishYZ.Init();
roomFishConfig = new Dictionary<GameTypeEnum, RoomFishConfig>();
createDic = new Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>>();
var list = GameManager.Instance.gameConfig.roomFishConfigs;
if (list == null || list.Count == 0)
return;
foreach (var item in list)
{
GameTypeEnum gameType = (GameTypeEnum)item.gameType;
// 安全添加(避免重复 key 抛异常)
roomFishConfig[gameType] = item;
// 初始化子字典
var fishDic = new Dictionary<string, RoomFishDetailConfig>();
createDic[gameType] = fishDic;
// 普通鱼
if (item.normalFishList != null)
{
foreach (var fish in item.normalFishList)
fishDic[fish.fishNumber] = fish;
}
// 等级鱼(若与基础鱼相同素材替换基础的)
if (item.roomFishLevelList != null)
{
foreach (var fish in item.roomFishLevelList)
fishDic[fish.fishNumber] = fish;
}
}
}
/// <summary>
/// 房间鱼配置(按游戏类型)
/// </summary>
public Dictionary<GameTypeEnum, RoomFishConfig> RoomFishConfig
{
get
{
EnsureInit();
return roomFishConfig;
}
}
/// <summary>
/// 鱼号 → 鱼配置(按游戏类型)
/// </summary>
public Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>> CreateDic
{
get
{
EnsureInit();
return createDic;
}
}
#endregion
#region // 鱼生成计时器相关
private NativeArray<float> timers;
private NativeArray<float> frequencies;
private NativeArray<int> shouldSpawn;
public GameObject dieFXPrefab;
private List<RoomFishDetailConfig> spawnList; // 当前房间的鱼配置
private Dictionary<string, RoomFishDetailConfig> spawnDic; // 当前房间的鱼配置
public void InitSpawnSystem(GameTypeEnum gameType)
{
EnsureInit();
var config = RoomFishConfig[gameType];
spawnList = new List<RoomFishDetailConfig>();
spawnDic = new Dictionary<string, RoomFishDetailConfig>();
// 合并普通鱼 + 等级鱼
//spawnList.AddRange(config.normalFishList);
//spawnList.AddRange(config.roomFishLevelList);
foreach (var item in config.normalFishList)
{
spawnDic.Add(item.fishNumber, item);
spawnDic[item.fishNumber] = item;
spawnList.Add(item);
}
foreach (var item in config.roomFishLevelList)
{
if (item.type==2)
{
if (item.roomLevel == GameManager.Instance.gameData.currRoomData.roomLevel)
{
spawnDic.Add(item.fishNumber, item);
spawnList.Add(item);
}
}
else
{
if (item.roomLevel == GameManager.Instance.gameData.currRoomData.roomLevel)
{
spawnDic.Add(item.fishNumber, item);
spawnList.Add(item);
}
}
}
int count = spawnList.Count;
timers = new NativeArray<float>(count, Allocator.Persistent);
frequencies = new NativeArray<float>(count, Allocator.Persistent);
shouldSpawn = new NativeArray<int>(count, Allocator.Persistent);
for (int i = 0; i < count; i++)
{
timers[i] = 0;
frequencies[i] = spawnList[i].fishFrequency;
shouldSpawn[i] = 0;
}
}
public void CloseSpawnSystem()
{
spawnList = null;
}
#endregion
/// <summary>
/// 鱼的父节点(用于层级管理)
/// </summary>
public Transform fishRoot;
protected void Awake()
{
if (fishRoot == null)
{
fishRoot = new GameObject("FishRoot").transform;
}
// CreateSingleFish();
new FishResourcesData(); //这里用来测试加载鱼预制体
EventCenter.Instance.AddEventListener<SyncGameData>(ConstEventString.SyncGameData_CreateFish, CreateFish);
}
private void OnDestroy()
{
EventCenter.Instance.RemoveEventListener<SyncGameData>(ConstEventString.SyncGameData_CreateFish, CreateFish);
}
public bool fangzhu;
private void Update()
{
if (spawnList == null)
return;
if (!fangzhu)
{
return;
}
var job = new FishSpawnTimerJob
{
deltaTime = Time.deltaTime,
timers = timers,
frequencies = frequencies,
shouldSpawn = shouldSpawn
};
JobHandle handle = job.Schedule();
handle.Complete();
// 主线程执行生成
for (int i = 0; i < spawnList.Count; i++)
{
if (shouldSpawn[i] == 1)
{
var fish = spawnList[i];
{
List<int> list;
int pathId;
if (fish.type==2)
{
//list = FishYZ.dicfishYZ[GameManager.Instance.gameConfig.fishArrayConfigs. fish.fishNumber];
pathId = 0;
}
else
{
list = FishDatas[fish.fishNumber].pathList;
pathId = list[Random.Range(0, list.Count)];
}
SyncGameData sgd = new SyncGameData
{
sitPos = GameManager.Instance.gameData.roomJoinNotice.position,
frameType = FrameDataType.createFish,
time = BeijingTimeManager.Instance.CurrentTimestampMs,
frameData = new FrameData_CreateFish
{
fishNumber = fish.fishNumber,
guid = Guid.NewGuid().ToString(),
moveLineId = pathId.ToString()
}
};
WebSocketSendList.SyncGameData(sgd);
}
//SpawnFishMainThread(fish);
}
}
}
public void CreateFish(SyncGameData syncGameData)
{
//if (syncGameData.sitPos == GameManager.Instance.gameData.roomJoinNotice.position)
{
var rotateData = JsonConvert.DeserializeObject<FrameData_CreateFish>(syncGameData.frameData.ToString());
SpawnFishMainThread(rotateData, syncGameData.time);
}
}
private async void SpawnFishMainThread(FrameData_CreateFish createFishData,long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber] ;
if (cfg.type==1)
{
bool flowControl = OnlyFish(createFishData,time);
if (!flowControl)
{
return;
}
}
else if (cfg.type==2)
{
//cfg.fishNumber;3
var yz = GameManager.Instance.gameConfig.fishArrayConfigs.Find(a => a.fishArrayNumber == cfg.fishNumber);
foreach (var item in GameManager.Instance.gameConfig.fishArrayConfigs)
{
if (item.arrayNumber==cfg.fishNumber)
{
Debug.Log(item);
}
}
FishTypeConfig fishType = null;
foreach (var item in M_GameConfig.fishTypeConfigs)
{
if (item.fishNumber == yz.fishNumber)
{
fishType = item;
}
}
// 3. 出生点
Vector3 pos = new Vector3(
9999, 9999, 0
);
var prefab = FishResourcesData.GetFishPrefab(fishType.fishNumber);
int pathId = 0;
int count = 0;
List<int> list = new List<int>();
switch (yz.arrayNumber.Substring(0, 3))
{
case "700":
list = FishYZ.dicfishYZ[yz.arrayNumber];
StartCoroutine( IeShanXing(createFishData, yz, pos, prefab, list,time));
break;
case "701":
list = FishYZ.dicfishYZ[yz.arrayNumber];
foreach (var item in list)
Quan(createFishData, yz, pos, prefab, item, 10, time);
break;
case "702":
list = FishYZ.dicfishYZ[yz.arrayNumber];
foreach (var item in list)
{
StartCoroutine(YZ7007(createFishData, yz, pos, prefab, item, time));
}
break;
case "7007":
list = FishYZ.dicfishYZ[yz.arrayNumber];
foreach (var item in list)
{
StartCoroutine(YZ7007(createFishData, yz, pos, prefab, item, time));
}
break;
default:
break;
}
//// 4. 实例化
//GameObject fish = Instantiate(prefab, pos, Quaternion.identity, fishRoot);
//var v = fish.GetComponent<MonsterContral>();
}
}
IEnumerator IeShanXing(FrameData_CreateFish createFishData, FishArrayConfig yz, Vector3 pos, GameObject prefab, List<int> list, long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber];
foreach (var item in list)
{
ShanXing(createFishData, yz, pos, prefab, item, 10, time);
yield return new WaitForSeconds(0.8f);
}
}
private void ShanXing(FrameData_CreateFish createFishData, FishArrayConfig yz, Vector3 pos, GameObject prefab, int pathId,int count, long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber];
for (int i = 1; i <= 16; i++)
{
// 4. 实例化
GameObject fish = Instantiate(prefab, pos, Quaternion.Euler((i * 5 * (i % 2 == 0 ? -1 : 1)) * Vector3.forward+prefab.transform.eulerAngles) , fishRoot);
var v = fish.GetComponent<MonsterContral>();
v.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
v.guid = createFishData.guid+i;
fishDatas_hashCodekey[v.guid] = v;
v.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs- time)/1000;
//int pathId = list[Random.Range(0, list.Count)];
v.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
}
}
private void Quan(FrameData_CreateFish createFishData, FishArrayConfig yz, Vector3 pos, GameObject prefab, int pathId,int count, long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber];
for (int i = 0; i < count; i++)
{
// 4. 实例化
GameObject fish = Instantiate(prefab, pos, Quaternion.Euler((360 / count) * i * Vector3.forward + prefab.transform.eulerAngles), fishRoot);
var v = fish.GetComponent<MonsterContral>();
v.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
v.guid = createFishData.guid + i;
fishDatas_hashCodekey[v.guid] = v;
v.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000;
//int pathId = list[Random.Range(0, list.Count)];
v.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
}
}
//顺序出
IEnumerator YZ7007(FrameData_CreateFish createFishData, FishArrayConfig yz, Vector3 pos, GameObject prefab, int pathId, long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber];
List<int> list = FishDatas[yz.fishNumber].pathList;
for (int i = 0; i < 8; i++)
{
yield return new WaitForSeconds(1f);
//// 4. 实例化
//GameObject fish = Instantiate(prefab, pos, Quaternion.Euler((360 / 20) * i * Vector3.forward), fishRoot);
//var v = fish.GetComponent<MonsterContral>();
//v.monsterData.roomFishDetailConfig = cfg;
//v.hashCode = v.gameObject.GetHashCode().ToString();
//fishDatas_hashCodekey[v.hashCode] = v;
////int pathId = list[Random.Range(0, list.Count)];
//v.Init(MonsterMoveLine.dic_BezierCurveDatas["鱼阵" + (pathId + 1)], 15, true, cfg.fishNumber);
//v.fishType = (FishTypeEnum)FishDatas[yz.fishNumber].fishType;
// 4. 实例化
GameObject fish = Instantiate(prefab, pos, prefab.transform.rotation, fishRoot);
var v = fish.GetComponent<MonsterContral>();
// 5. 初始化路径
if (v == null)
{
v = fish.AddComponent<MonsterContral>();
}
v.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
v.guid = createFishData.guid+i;
v.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000;
fishDatas_hashCodekey[v.guid] = v;
v.Init(pathId.ToString(), 10);
}
}
private bool OnlyFish(FrameData_CreateFish createFishData,long time)
{
RoomFishDetailConfig cfg = spawnDic[createFishData.fishNumber];
// 1. 找到鱼的基础配置
FishTypeConfig fishType = M_GameConfig.fishTypeConfigs
.Find(f => f.fishNumber == cfg.fishNumber);
if (fishType == null)
{
Debug.LogError($"找不到鱼配置:{cfg.fishNumber}");
return false;
}
// 2. 加载 Prefab(imageUrl 你可以换成自己的字段)
//var prefab = await Addressables.LoadAssetAsync<GameObject>(fishType.imageUrl).Task;
var prefab = FishResourcesData.GetFishPrefab(fishType.fishNumber);
// 3. 出生点
Vector3 pos = new Vector3(
9999, 9999, 0
);
// 4. 实例化
GameObject fish = Instantiate(prefab, pos, prefab.transform.rotation, fishRoot);
var v = fish.GetComponent<MonsterContral>();
// 5. 初始化路径
if (v == null)
{
v = fish.AddComponent<MonsterContral>();
}
v.monsterData.fishTypeConfig = FishDatas[cfg.fishNumber];
v.guid = createFishData.guid;
v.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000;
fishDatas_hashCodekey[v.guid] = v;
var list = FishDatas[cfg.fishNumber].pathList;
string pathId = createFishData.moveLineId;
v.Init(pathId, 10);
//v.monsterData.moveLine.Init(MonsterMoveLine.dic_BezierCurveDatas["曲线" + Random.Range(1, 4).ToString()], 10);
////初始化
//GameObject obj = Instantiate(prefab, Vector3.one * 999, Quaternion.identity);
//var v = obj.GetComponent<MonsterControl>();
////v.dic_AnimKeyAnimName.Add(CharacterAnimationType.move, "stand2");
//v.monsterData.moveLine.Init(MonsterMoveLine.dic_BezierCurveDatas["曲线" + Random.Range(1, 4).ToString()], 10);
Debug.Log($"生成鱼:{fishType.fishName}");
return true;
}
public void CreateFishArray(string arrayNumber)
{
var array = M_GameConfig.fishArrayConfigs
.Find(a => a.fishArrayNumber == arrayNumber);
if (array == null)
{
Debug.LogError($"找不到鱼阵:{arrayNumber}");
return;
}
// 未来扩展:阵型、路径、Boss、普通鱼
//// array.ty.fishNumber
// // 2. 加载 Prefab(imageUrl 你可以换成自己的字段)
// //var prefab = await Addressables.LoadAssetAsync<GameObject>(fishType.imageUrl).Task;
// var prefab = FishResourcesData.CreateFishPrefab(fishType.fishNumber);
// // 3. 随机出生点
// Vector3 pos = new Vector3(
// Random.Range(-8f, 8f),
// Random.Range(-5f, 5f),
// 0
// );
// // 4. 实例化
// GameObject fish = Instantiate(prefab, pos, Quaternion.identity, fishRoot);
// var v = fish.GetComponent<MonsterContral>();
// // 5. 初始化路径
// if (v == null)
// {
// v = fish.
//
//
// <MonsterContral>();
// }
// v.monsterData.roomFishDetailConfig = cfg;
// v.hashCode = v.gameObject.GetHashCode().ToString();
// fishDatas_hashCodekey[v.hashCode] = v;
// var list = FishDatas[cfg.fishNumber].pathList;
// int pathId = list[Random.Range(0, list.Count)];
// v.monsterData.moveLine.Init(MonsterMoveLine.dic_BezierCurveDatas["曲线" + pathId], 10);
// v.fishType = (FishTypeEnum)FishDatas[cfg.fishNumber].fishType;
// //v.monsterData.moveLine.Init(MonsterMoveLine.dic_BezierCurveDatas["曲线" + Random.Range(1, 4).ToString()], 10);
// ////初始化
// //GameObject obj = Instantiate(prefab, Vector3.one * 999, Quaternion.identity);
// //var v = obj.GetComponent<MonsterControl>();
// ////v.dic_AnimKeyAnimName.Add(CharacterAnimationType.move, "stand2");
// //v.monsterData.moveLine.Init(MonsterMoveLine.dic_BezierCurveDatas["曲线" + Random.Range(1, 4).ToString()], 10);
// Debug.Log($"生成鱼:{fishType.fishName}");
}
public void EnterRoom(GameTypeEnum gameType)
{
InitSpawnSystem(gameType);
}
public void ExitRoom()
{
CloseSpawnSystem();
}
// ============================================================
// 1. 生成单条鱼
// ============================================================
public async void CreateSingleFish(string fishNumber, int pathId)
{
switch ((GameTypeEnum)GameManager.Instance.gameData.currGameType)
{
case GameTypeEnum.风雷之渊:
break;
case GameTypeEnum.太古仙墟:
break;
case GameTypeEnum.中国象棋:
break;
case GameTypeEnum.星际迷航:
break;
case GameTypeEnum.黑神话悟空:
break;
default:
break;
}
}
public void DesFish(string msg)
{
var killFish = JsonConvert.DeserializeObject<WebSocketResponseBase<RoomKillNotice>>(msg).arguments[0];
Debug.Log("时间123:" + (DateTimeOffset.Now.ToUnixTimeSeconds() - killFish.timespan) + "秒");
if (fishDatas_hashCodekey.ContainsKey(killFish.fishId))
{
var monster = fishDatas_hashCodekey[killFish.fishId];
Instantiate(monster.effect_Die == null ? dieFXPrefab : monster.effect_Die, monster.transform.position, Quaternion.identity, transform.parent);
Destroy(monster.gameObject);
fishDatas_hashCodekey.Remove(killFish.fishId);
//GameManager.Instance.gameData.roomJoinNotice.gold += killFish.gold;
var list = UIManager.Instance.Get<GameMainPanel_XJMH>(UIPanel.MainGamePanelXJMH).list_Sits;
foreach (var item in list)
{
if (item.user!=null)
{
if (item.user==killFish.userId)
{
item.goldNum +=killFish.gold;
}
}
}
}
}
}