2026-04-29 01:18:39 +08:00
|
|
|
|
// ============================================================
|
|
|
|
|
|
// 文件:CreateFishManager.cs
|
|
|
|
|
|
// 职责:捕鱼游戏 —— 鱼的生成 / 销毁 / 鱼阵管理核心管理器
|
|
|
|
|
|
// 优化点:
|
|
|
|
|
|
// 1. 消除 Update 中重复创建 List、字典查找性能问题
|
|
|
|
|
|
// 2. 统一鱼阵路线选取逻辑,减少冗余代码
|
|
|
|
|
|
// 3. FishSpawnTimerJob shouldSpawn 逻辑修正(原逻辑只在 ==0 时计时,现保持一致)
|
|
|
|
|
|
// 4. 增加必要的空检查与防御性编程
|
|
|
|
|
|
// 5. 清理无用注释与废弃代码块
|
|
|
|
|
|
// 6. 方法职责单一化拆分
|
|
|
|
|
|
// ============================================================
|
|
|
|
|
|
|
|
|
|
|
|
using Assets.MyGame.Scripts.Characters.Monster;
|
2026-03-27 15:18:35 +08:00
|
|
|
|
using Assets.MyGame.Scripts.Net;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
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;
|
2026-02-09 10:44:38 +08:00
|
|
|
|
using cfg;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
using System;
|
2026-02-09 10:44:38 +08:00
|
|
|
|
using System.Collections;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
using System.Collections.Generic;
|
2026-03-27 15:18:35 +08:00
|
|
|
|
using System.Linq;
|
2026-04-25 00:12:55 +08:00
|
|
|
|
using TMPro;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
using Unity.Collections;
|
|
|
|
|
|
using Unity.Jobs;
|
|
|
|
|
|
using UnityEngine;
|
2026-04-29 23:53:55 +08:00
|
|
|
|
using static UnityEditor.FilePathAttribute;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
using Random = UnityEngine.Random;
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 捕鱼游戏核心管理器:负责鱼的定时生成、网络同步、阵型调度、死亡特效。
|
|
|
|
|
|
/// 继承 MonoSingleton 保证全局唯一。
|
|
|
|
|
|
/// </summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public class CreateFishManager : MonoSingleton<CreateFishManager>
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// 外部依赖
|
|
|
|
|
|
// ----------------------------------------------------------------
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>当前游戏全局配置(通过 GameManager 获取)</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public GameConfig M_GameConfig => GameManager.Instance.gameConfig;
|
2026-03-27 15:18:35 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// 配置缓存(空间换时间,避免 List.Find O(n) 查找)
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>roomFishConfigs 按游戏类型索引</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
private Dictionary<GameTypeEnum, RoomFishConfig> roomFishConfig;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>每个游戏类型下 fishNumber → RoomFishDetailConfig</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
private Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>> createDic;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>fishNumber → FishTypeConfig(基础配置缓存)</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
private Dictionary<string, FishTypeConfig> fishDatas;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>fishArrayNumber → FishArrayConfig(鱼阵配置缓存)</summary>
|
2026-04-03 18:32:19 +08:00
|
|
|
|
private Dictionary<string, FishArrayConfig> fishArrayConfigDic;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>fishNumber → FishTypeConfig(与 fishDatas 相同来源,供内部高频使用)</summary>
|
2026-04-03 18:32:19 +08:00
|
|
|
|
private Dictionary<string, FishTypeConfig> fishTypeConfigDic;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// 运行时鱼实例字典(guid 为 key)
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>全部存活鱼(包含 Boss / 小鱼 / 黄金鱼)</summary>
|
|
|
|
|
|
public Dictionary<string, MonsterContral> fishDatas_hashCodekey = new Dictionary<string, MonsterContral>();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>Boss 鱼</summary>
|
|
|
|
|
|
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>();
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// UI 引用
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>当前游戏面板(用于坐标转换、金币飞行等)</summary>
|
2026-04-24 22:51:34 +08:00
|
|
|
|
public GameMainPanel_FishBase currGameType;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// 死亡特效 Prefab(Inspector 赋值)
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public GameObject dieFXPrefab; // 基础死亡特效
|
|
|
|
|
|
public GameObject dieFXPrefabAward; // 普通鱼金币奖励特效
|
|
|
|
|
|
public GameObject dieFXPrefabAwardTmp; // Boss 分数浮动文本
|
|
|
|
|
|
public GameObject dieFXPrefabAwardTmp_AddScore;
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// 生成系统运行时数据
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>鱼的父节点(保持场景层级整洁)</summary>
|
|
|
|
|
|
public Transform fishRoot;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>当前房间可生成鱼列表(与 NativeArray 下标对齐)</summary>
|
|
|
|
|
|
public List<RoomFishDetailConfig> spawnList;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>当前房间 fishNumber → RoomFishDetailConfig</summary>
|
|
|
|
|
|
public Dictionary<string, RoomFishDetailConfig> spawnDic;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>按鱼类型分类的生成配置(Boss / 普通 / 黄金…)</summary>
|
|
|
|
|
|
private Dictionary<FishTypeEnum, List<RoomFishDetailConfig>> fishTypeConfig;
|
|
|
|
|
|
|
|
|
|
|
|
// ------ 鱼阵路线相关 ------
|
|
|
|
|
|
/// <summary>arrayNumber → 该阵型所有可用生成配置</summary>
|
|
|
|
|
|
private Dictionary<string, List<RoomFishDetailConfig>> yz_FishConfig_Line;
|
|
|
|
|
|
/// <summary>列表下标 → arrayNumber(用于随机取阵型)</summary>
|
|
|
|
|
|
private Dictionary<int, string> yz_FishConfig_Line_Dic;
|
|
|
|
|
|
/// <summary>arrayNumber → 列表下标(反向索引)</summary>
|
|
|
|
|
|
private Dictionary<string, int> yz_FishConfig_Line_Dic1;
|
|
|
|
|
|
/// <summary>二维列表,与字典保持同步(供随机无重复取阵型用)</summary>
|
|
|
|
|
|
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 float bossTimer = 1f; // Boss 刷新倒计时(秒)
|
|
|
|
|
|
private float yzTimer; // 鱼阵刷新倒计时(秒)
|
|
|
|
|
|
private float ptTimer = 3f; // 普通鱼批量启用倒计时(秒)
|
|
|
|
|
|
private int yzCount; // 本轮同时激活阵型数量
|
|
|
|
|
|
private int ptCount; // 本轮同时启用普通鱼数量
|
|
|
|
|
|
private int yz_LineCount = 0; // 场景内鱼阵路线总数
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>是否开启放鱼(false 时 Update 不执行生成逻辑)</summary>
|
|
|
|
|
|
public bool fangzhu;
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 懒加载属性
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 鱼基础配置字典(fishNumber → FishTypeConfig),首次访问时构建。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<string, FishTypeConfig> FishDatas
|
2026-04-03 18:32:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
if (fishDatas != null) return fishDatas;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
fishDatas = new Dictionary<string, FishTypeConfig>(M_GameConfig.fishTypeConfigs.Count);
|
|
|
|
|
|
foreach (var item in M_GameConfig.fishTypeConfigs)
|
|
|
|
|
|
fishDatas[item.fishNumber] = item;
|
|
|
|
|
|
|
|
|
|
|
|
return fishDatas;
|
|
|
|
|
|
}
|
2026-04-03 18:32:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 房间鱼配置(按游戏类型),首次访问时触发懒加载初始化。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<GameTypeEnum, RoomFishConfig> RoomFishConfig
|
|
|
|
|
|
{
|
|
|
|
|
|
get { EnsureInit(); return roomFishConfig; }
|
|
|
|
|
|
}
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 游戏类型 → (fishNumber → RoomFishDetailConfig),首次访问时触发懒加载。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>> CreateDic
|
|
|
|
|
|
{
|
|
|
|
|
|
get { EnsureInit(); return createDic; }
|
|
|
|
|
|
}
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ================================================================
|
|
|
|
|
|
// Unity 生命周期
|
|
|
|
|
|
// ================================================================
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
protected override void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Awake();
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 确保 FishRoot 存在
|
|
|
|
|
|
if (fishRoot == null)
|
|
|
|
|
|
fishRoot = new GameObject("FishRoot").transform;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 监听服务器下发的创鱼事件
|
|
|
|
|
|
EventCenter.Instance.AddEventListener<SyncGameData>(
|
|
|
|
|
|
ConstEventString.SyncGameData_CreateFish, CreateFish);
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 随机初始化计时器,避免所有类型同帧触发
|
|
|
|
|
|
yzTimer = Random.Range(2f, 6f);
|
|
|
|
|
|
yzCount = Random.Range(2, 5);
|
|
|
|
|
|
ptCount = Random.Range(1, 4);
|
|
|
|
|
|
}
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
private void OnDestroy()
|
|
|
|
|
|
{
|
|
|
|
|
|
EventCenter.Instance.RemoveEventListener<SyncGameData>(
|
|
|
|
|
|
ConstEventString.SyncGameData_CreateFish, CreateFish);
|
|
|
|
|
|
|
|
|
|
|
|
// 释放 NativeArray,避免内存泄漏
|
|
|
|
|
|
DisposeNativeArrays();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// Update:定时调度 + Job 驱动生成
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 未初始化 或 未开启放鱼 → 跳过
|
|
|
|
|
|
if (spawnList == null || !fangzhu) return;
|
|
|
|
|
|
|
|
|
|
|
|
float dt = Time.deltaTime;
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 1. 用 Job System 并行更新所有鱼的计时器 ----
|
|
|
|
|
|
var job = new FishSpawnTimerJob
|
|
|
|
|
|
{
|
|
|
|
|
|
deltaTime = dt,
|
|
|
|
|
|
timers = timers,
|
|
|
|
|
|
frequencies = frequencies,
|
|
|
|
|
|
shouldSpawn = shouldSpawn,
|
|
|
|
|
|
};
|
|
|
|
|
|
job.Schedule().Complete();
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 2. Boss 定时激活 ----
|
|
|
|
|
|
TickBossSpawn(dt);
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 3. 鱼阵定时激活 ----
|
|
|
|
|
|
TickFishArraySpawn(dt);
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 4. 普通鱼定时批量激活 ----
|
|
|
|
|
|
TickNormalFishSpawn(dt);
|
|
|
|
|
|
|
|
|
|
|
|
// ---- 5. 遍历 shouldSpawn,向服务器发送生成请求 ----
|
|
|
|
|
|
ProcessSpawnRequests();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 定时 Tick 方法(由 Update 调用)
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>每 25 秒随机激活一条 Boss 鱼。</summary>
|
|
|
|
|
|
private void TickBossSpawn(float dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
bossTimer -= dt;
|
|
|
|
|
|
if (bossTimer > 0f) return;
|
|
|
|
|
|
|
|
|
|
|
|
bossTimer = 25f;
|
|
|
|
|
|
|
|
|
|
|
|
if (!fishTypeConfig.TryGetValue(FishTypeEnum.Boss鱼, out var bossList) || bossList.Count == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
bossList[Random.Range(0, bossList.Count)].isCreate = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>每 1~3 秒随机激活若干组鱼阵。</summary>
|
|
|
|
|
|
private void TickFishArraySpawn(float dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
yzTimer -= dt;
|
|
|
|
|
|
if (yzTimer > 0f) return;
|
|
|
|
|
|
|
|
|
|
|
|
yzTimer = Random.Range(1f, 3f);
|
|
|
|
|
|
yzCount = Random.Range(2, 5);
|
|
|
|
|
|
|
|
|
|
|
|
int lineCount = yz_FishConfig_Line_List.Count;
|
|
|
|
|
|
if (lineCount == 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 随机选 yzCount 个不重复的阵型下标
|
|
|
|
|
|
var selectedIndices = RandomUniqueNumbers(
|
|
|
|
|
|
Mathf.Min(yzCount, lineCount), 0, lineCount);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (int idx in selectedIndices)
|
|
|
|
|
|
{
|
|
|
|
|
|
string arrayNumber = yz_FishConfig_Line_Dic[idx];
|
|
|
|
|
|
if (!yz_FishConfig_Line.TryGetValue(arrayNumber, out var lineList) || lineList.Count == 0)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 随机选一条配置并标记为待生成
|
|
|
|
|
|
var chosen = lineList[Random.Range(0, lineList.Count)];
|
|
|
|
|
|
chosen.isCreate = 2;
|
|
|
|
|
|
|
|
|
|
|
|
// 同步更新 spawnDic 中的状态
|
|
|
|
|
|
if (spawnDic.TryGetValue(chosen.fishNumber, out var spawnEntry))
|
|
|
|
|
|
spawnEntry.isCreate = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>每 3 秒随机批量激活若干条普通鱼。</summary>
|
|
|
|
|
|
private void TickNormalFishSpawn(float dt)
|
|
|
|
|
|
{
|
|
|
|
|
|
ptTimer -= dt;
|
|
|
|
|
|
if (ptTimer > 0f) return;
|
|
|
|
|
|
|
|
|
|
|
|
ptTimer = 3f;
|
|
|
|
|
|
ptCount = Random.Range(1, 4);
|
|
|
|
|
|
|
|
|
|
|
|
if (!fishTypeConfig.TryGetValue(FishTypeEnum.普通鱼, out var normalList) || normalList.Count == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 随机选 ptCount 个不重复下标
|
|
|
|
|
|
var indices = RandomUniqueNumbers(
|
|
|
|
|
|
Mathf.Min(ptCount, normalList.Count), 0, normalList.Count);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (int idx in indices)
|
|
|
|
|
|
normalList[idx].isCreate = 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 遍历 shouldSpawn 数组,对本帧到期且被标记 isCreate==2 的鱼
|
|
|
|
|
|
/// 向服务器发送 WebSocket 生成同步包。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ProcessSpawnRequests()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < spawnList.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (shouldSpawn[i] != 1) continue;
|
|
|
|
|
|
|
|
|
|
|
|
var fish = spawnList[i];
|
|
|
|
|
|
|
|
|
|
|
|
// isCreate==0:刚到期,重置为冷却中,等待外部计时器激活
|
|
|
|
|
|
if (fish.isCreate == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
fish.isCreate = 1; // 标记为"已处理但未激活"
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// isCreate==2:已被激活,向服务器同步一次生成请求
|
|
|
|
|
|
if (fish.isCreate == 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
SendCreateFishRequest(fish);
|
|
|
|
|
|
fish.isCreate = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构建并发送生成鱼的 WebSocket 同步数据包。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SendCreateFishRequest(RoomFishDetailConfig fish)
|
|
|
|
|
|
{
|
|
|
|
|
|
int pathId = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 普通鱼(type==1)才从 pathList 随机选路径;鱼阵(type==2)由后续逻辑决定
|
|
|
|
|
|
if (fish.type == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pathList = FishDatas[fish.fishNumber].pathList;
|
|
|
|
|
|
if (pathList != null && pathList.Count > 0)
|
|
|
|
|
|
pathId = pathList[Random.Range(0, pathList.Count)];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var 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);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 初始化 / 清理
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 懒加载初始化:只执行一次,构建全部配置缓存字典。
|
|
|
|
|
|
/// </summary>
|
2026-04-03 18:32:19 +08:00
|
|
|
|
private void EnsureInit()
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (roomFishConfig != null) return;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
|
|
|
|
|
FishYZ.Init();
|
|
|
|
|
|
roomFishConfig = new Dictionary<GameTypeEnum, RoomFishConfig>();
|
2026-04-29 01:18:39 +08:00
|
|
|
|
createDic = new Dictionary<GameTypeEnum, Dictionary<string, RoomFishDetailConfig>>();
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
|
|
|
|
|
var list = GameManager.Instance.gameConfig.roomFishConfigs;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (list == null || list.Count == 0) return;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 构建 fishArray / fishType 字典缓存
|
2026-04-03 18:32:19 +08:00
|
|
|
|
BuildConfigCache();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in list)
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var gameType = (GameTypeEnum)item.gameType;
|
2026-04-03 18:32:19 +08:00
|
|
|
|
roomFishConfig[gameType] = item;
|
|
|
|
|
|
|
|
|
|
|
|
var fishDic = new Dictionary<string, RoomFishDetailConfig>();
|
|
|
|
|
|
createDic[gameType] = fishDic;
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 普通鱼列表
|
2026-04-03 18:32:19 +08:00
|
|
|
|
if (item.normalFishList != null)
|
|
|
|
|
|
foreach (var fish in item.normalFishList)
|
|
|
|
|
|
fishDic[fish.fishNumber] = fish;
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 等级鱼列表(同 fishNumber 会覆盖普通鱼,实现换皮)
|
2026-04-03 18:32:19 +08:00
|
|
|
|
if (item.roomFishLevelList != null)
|
|
|
|
|
|
foreach (var fish in item.roomFishLevelList)
|
|
|
|
|
|
fishDic[fish.fishNumber] = fish;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// 构建高频查询的字典缓存(fishArrayConfigs / fishTypeConfigs)。
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// </summary>
|
2026-04-29 01:18:39 +08:00
|
|
|
|
private void BuildConfigCache()
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
fishArrayConfigDic = GameManager.Instance.gameConfig.fishArrayConfigs
|
|
|
|
|
|
.ToDictionary(a => a.fishArrayNumber, a => a);
|
|
|
|
|
|
|
|
|
|
|
|
fishTypeConfigDic = GameManager.Instance.gameConfig.fishTypeConfigs
|
|
|
|
|
|
.ToDictionary(f => f.fishNumber, f => f);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 进入房间时初始化生成系统:加载当前房间配置、分配 NativeArray。
|
|
|
|
|
|
/// </summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public void InitSpawnSystem(GameTypeEnum gameType)
|
|
|
|
|
|
{
|
|
|
|
|
|
EnsureInit();
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化分类容器
|
|
|
|
|
|
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>();
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
var config = RoomFishConfig[gameType];
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ---- 处理普通鱼列表 ----
|
|
|
|
|
|
if (config.normalFishList != null)
|
2026-03-18 17:26:14 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
foreach (var item in config.normalFishList)
|
2026-03-27 15:18:35 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
spawnDic[item.fishNumber] = item;
|
|
|
|
|
|
spawnList.Add(item);
|
|
|
|
|
|
|
|
|
|
|
|
if (item.type == 1)
|
2026-03-27 15:18:35 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 单体鱼:按鱼类型分组
|
|
|
|
|
|
AddToFishTypeConfig(item);
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
else if (item.type == 2)
|
2026-03-27 15:18:35 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 鱼阵:按 arrayNumber 分组
|
|
|
|
|
|
TryAddToArrayLine(item);
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-18 17:26:14 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
// ---- 处理等级鱼列表(仅当前房间等级)----
|
|
|
|
|
|
int currRoomLevel = GameManager.Instance.gameData.currRoomData.roomLevel;
|
|
|
|
|
|
if (config.roomFishLevelList != null)
|
2026-03-18 17:26:14 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
foreach (var item in config.roomFishLevelList)
|
2026-03-18 17:26:14 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (item.roomLevel != currRoomLevel) continue;
|
|
|
|
|
|
|
2026-03-27 15:18:35 +08:00
|
|
|
|
if (item.type == 2)
|
2026-03-18 17:26:14 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
spawnDic[item.fishNumber] = item;
|
2026-03-27 15:18:35 +08:00
|
|
|
|
spawnList.Add(item);
|
2026-04-29 01:18:39 +08:00
|
|
|
|
TryAddToArrayLine(item);
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
AddToFishTypeConfig(item);
|
|
|
|
|
|
// 等级鱼也加入 spawnDic / spawnList
|
|
|
|
|
|
spawnDic[item.fishNumber] = item;
|
|
|
|
|
|
spawnList.Add(item);
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-18 17:26:14 +08:00
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ---- 分配 Job System NativeArray ----
|
2026-02-03 11:35:19 +08:00
|
|
|
|
int count = spawnList.Count;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
DisposeNativeArrays(); // 防止重复进房泄漏
|
|
|
|
|
|
timers = new NativeArray<float>(count, Allocator.Persistent);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
frequencies = new NativeArray<float>(count, Allocator.Persistent);
|
2026-04-29 01:18:39 +08:00
|
|
|
|
shouldSpawn = new NativeArray<int>(count, Allocator.Persistent);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
timers[i] = 0f;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
frequencies[i] = spawnList[i].fishFrequency;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
shouldSpawn[i] = 1; // 初始全部允许生成
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ---- 统计场景内鱼阵路线总数 ----
|
|
|
|
|
|
yz_LineCount = 0;
|
|
|
|
|
|
foreach (var key in MonsterMoveLine.dic_BezierCurveDatas.Keys)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (key.StartsWith("鱼阵"))
|
|
|
|
|
|
yz_LineCount++;
|
|
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将单体鱼配置按 FishTypeEnum 加入分类字典。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void AddToFishTypeConfig(RoomFishDetailConfig item)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!FishDatas.TryGetValue(item.fishNumber, out var ft)) return;
|
|
|
|
|
|
|
|
|
|
|
|
var typeEnum = (FishTypeEnum)ft.fishType;
|
|
|
|
|
|
if (!fishTypeConfig.ContainsKey(typeEnum))
|
|
|
|
|
|
fishTypeConfig[typeEnum] = new List<RoomFishDetailConfig>();
|
|
|
|
|
|
|
|
|
|
|
|
fishTypeConfig[typeEnum].Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将鱼阵配置按 arrayNumber 加入路线字典(使用缓存替代 List.Find)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void TryAddToArrayLine(RoomFishDetailConfig item)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fishArrayConfigDic.TryGetValue(item.fishNumber, out var yz)) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!yz_FishConfig_Line.ContainsKey(yz.arrayNumber))
|
|
|
|
|
|
{
|
|
|
|
|
|
yz_FishConfig_Line[yz.arrayNumber] = new List<RoomFishDetailConfig>();
|
|
|
|
|
|
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_Dic1[yz.arrayNumber] = newIdx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
yz_FishConfig_Line[yz.arrayNumber].Add(item);
|
|
|
|
|
|
yz_FishConfig_Line_List[yz_FishConfig_Line_Dic1[yz.arrayNumber]].Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关闭生成系统:清理列表,销毁场景内所有鱼对象。
|
|
|
|
|
|
/// </summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public void CloseSpawnSystem()
|
|
|
|
|
|
{
|
|
|
|
|
|
spawnList = null;
|
2026-04-29 23:53:55 +08:00
|
|
|
|
spawnDic = null;
|
|
|
|
|
|
yz_FishConfig_Line_Dic = null;
|
|
|
|
|
|
yz_FishConfig_Line = null;
|
|
|
|
|
|
yz_FishConfig_Line_Dic1 = null;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (fishRoot == null) return;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = fishRoot.childCount - 1; i >= 0; i--)
|
2026-04-03 18:32:19 +08:00
|
|
|
|
Destroy(fishRoot.GetChild(i).gameObject);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>释放 NativeArray(避免 Unity 内存泄漏警告)。</summary>
|
|
|
|
|
|
private void DisposeNativeArrays()
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (timers.IsCreated) timers.Dispose();
|
|
|
|
|
|
if (frequencies.IsCreated) frequencies.Dispose();
|
|
|
|
|
|
if (shouldSpawn.IsCreated) shouldSpawn.Dispose();
|
2026-03-27 15:18:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 进退房间接口
|
|
|
|
|
|
// ================================================================
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>进入房间:初始化生成系统并绑定游戏面板。</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public void EnterRoom(GameTypeEnum gameType)
|
|
|
|
|
|
{
|
|
|
|
|
|
InitSpawnSystem(gameType);
|
2026-04-29 01:18:39 +08:00
|
|
|
|
BindCurrentGamePanel();
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>退出房间:关闭生成系统。</summary>
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public void ExitRoom()
|
|
|
|
|
|
{
|
|
|
|
|
|
CloseSpawnSystem();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>根据当前 GameType 绑定对应 UI 面板到 currGameType。</summary>
|
|
|
|
|
|
private void BindCurrentGamePanel()
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
switch (GameManager.Instance.gameData.currGameType)
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
case GameType.FLZY:
|
|
|
|
|
|
currGameType = UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelFLZY);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
break;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
case GameType.TGXX:
|
|
|
|
|
|
currGameType = UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelTGXX);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
break;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
case GameType.XJMH:
|
|
|
|
|
|
currGameType = UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelXJMH);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
break;
|
2026-04-29 01:18:39 +08:00
|
|
|
|
case GameType.HHWK:
|
|
|
|
|
|
currGameType = UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelHHWK);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-23 17:24:31 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 网络回调:创建鱼
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
2026-04-23 17:24:31 +08:00
|
|
|
|
/// <summary>
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// 收到服务器 SyncGameData 创鱼事件,反序列化并执行实例化。
|
2026-04-23 17:24:31 +08:00
|
|
|
|
/// </summary>
|
2026-04-29 01:18:39 +08:00
|
|
|
|
public void CreateFish(SyncGameData syncGameData)
|
2026-04-23 17:24:31 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var rotateData = JsonConvert.DeserializeObject<FrameData_CreateFish>(
|
|
|
|
|
|
syncGameData.frameData.ToString());
|
|
|
|
|
|
SpawnFishMainThread(rotateData, syncGameData.time);
|
|
|
|
|
|
}
|
2026-04-24 22:51:34 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 主线程实例化鱼对象(单体鱼 / 鱼阵分发)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void SpawnFishMainThread(FrameData_CreateFish createFishData, long time)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!spawnDic.TryGetValue(createFishData.fishNumber, out var cfg))
|
2026-04-23 17:24:31 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
Debug.LogWarning($"[CreateFishManager] 找不到 spawnDic 配置: {createFishData.fishNumber}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cfg.type == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 单体鱼
|
|
|
|
|
|
OnlyFish(createFishData, time);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (cfg.type == 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 鱼阵
|
|
|
|
|
|
SpawnFishArray(createFishData, cfg, time);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 单体鱼生成
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 生成一条普通/Boss/黄金鱼并初始化路径。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>成功返回 true,配置缺失返回 false。</returns>
|
|
|
|
|
|
private bool OnlyFish(FrameData_CreateFish createFishData, long time)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fishTypeConfigDic.TryGetValue(createFishData.fishNumber, out var fishType))
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"[CreateFishManager] 找不到 fishTypeConfig: {createFishData.fishNumber}");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 23:53:55 +08:00
|
|
|
|
//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);
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
|
|
// 按鱼类型放入对应字典
|
|
|
|
|
|
RegisterFishInstance(mc, fishType.fishType);
|
|
|
|
|
|
|
|
|
|
|
|
mc.Init(createFishData.moveLineId, spawnDic[createFishData.fishNumber].times);
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log($"[CreateFishManager] 生成鱼:{fishType.fishName}");
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>将鱼实例注册到全局字典及对应分类字典。</summary>
|
|
|
|
|
|
private void RegisterFishInstance(MonsterContral mc, int fishTypeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
fishDatas_hashCodekey[mc.guid] = mc;
|
|
|
|
|
|
|
|
|
|
|
|
switch (fishTypeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1: // 普通鱼
|
|
|
|
|
|
case 3: // 特殊鱼 / 黄金鱼
|
|
|
|
|
|
fishDatas_hashCodekey_Small[mc.guid] = mc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2: // Boss
|
|
|
|
|
|
fishDatas_hashCodekey_Boss[mc.guid] = mc;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 鱼阵生成(按 arrayNumber 前缀分发到对应阵型协程/方法)
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>根据鱼阵配置分发到对应的生成逻辑。</summary>
|
|
|
|
|
|
private void SpawnFishArray(FrameData_CreateFish createFishData, RoomFishDetailConfig cfg, long time)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fishArrayConfigDic.TryGetValue(cfg.fishNumber, out var yz))
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"[CreateFishManager] 找不到 fishArrayConfig: {cfg.fishNumber}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!fishTypeConfigDic.TryGetValue(yz.fishNumber, out var fishType))
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"[CreateFishManager] 鱼阵 fishType 缺失: {yz.fishNumber}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"[CreateFishManager] 鱼阵路线为空: {yz.arrayNumber}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string prefix = yz.arrayNumber.Length >= 3
|
|
|
|
|
|
? yz.arrayNumber.Substring(0, 3)
|
|
|
|
|
|
: yz.arrayNumber;
|
|
|
|
|
|
|
|
|
|
|
|
switch (prefix)
|
|
|
|
|
|
{
|
|
|
|
|
|
case "700": // 扇形阵:逐条延迟生成
|
|
|
|
|
|
StartCoroutine(IeShanXing(createFishData, yz, pos, prefab, pathList, time, yz.fishCount));
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "701": // 环形阵:同帧同路径全部生成
|
|
|
|
|
|
foreach (int pathId in pathList)
|
|
|
|
|
|
Quan(createFishData, yz, pos, prefab, pathId, yz.fishCount, time);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case "702":
|
|
|
|
|
|
case "7007":
|
|
|
|
|
|
case "710": // 顺序阵:每条路径逐一延迟生成
|
|
|
|
|
|
int chosen710 = (prefix == "710")
|
|
|
|
|
|
? pathList[Random.Range(0, pathList.Count)]
|
|
|
|
|
|
: -1;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (int pathId in pathList)
|
|
|
|
|
|
{
|
|
|
|
|
|
int actualPath = (prefix == "710") ? chosen710 : pathId;
|
|
|
|
|
|
StartCoroutine(YZ7007(createFishData, yz, pos, prefab, actualPath, time, yz.fishCount));
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
Debug.LogWarning($"[CreateFishManager] 未知鱼阵前缀: {prefix}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 鱼阵生成协程 / 方法
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>扇形阵:按路线列表逐条延迟 0.8s 生成一扇。</summary>
|
|
|
|
|
|
private IEnumerator IeShanXing(FrameData_CreateFish createFishData, FishArrayConfig yz,
|
|
|
|
|
|
Vector3 pos, GameObject prefab, List<int> pathList, long time, int count)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (int pathId in pathList)
|
|
|
|
|
|
{
|
|
|
|
|
|
ShanXing(createFishData, yz, pos, prefab, pathId, count, time);
|
|
|
|
|
|
yield return new WaitForSeconds(0.8f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 扇形阵单扇:生成 16 条鱼,每条旋转角度递增(±5°交替),模拟扇形展开。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ShanXing(FrameData_CreateFish createFishData, FishArrayConfig yz,
|
|
|
|
|
|
Vector3 pos, GameObject prefab, int pathId, int count, long time)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cfg = spawnDic[createFishData.fishNumber];
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= 16; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 交替正负角度,形成扇形分布
|
|
|
|
|
|
float angle = i * 5f * (i % 2 == 0 ? -1f : 1f);
|
|
|
|
|
|
var rotation = Quaternion.Euler(
|
|
|
|
|
|
prefab.transform.eulerAngles + Vector3.forward * angle);
|
|
|
|
|
|
|
2026-04-29 23:53:55 +08:00
|
|
|
|
//var fish = Instantiate(prefab, pos, rotation, fishRoot);
|
|
|
|
|
|
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, rotation, fishRoot);
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var mc = fish.GetComponent<MonsterContral>();
|
|
|
|
|
|
|
|
|
|
|
|
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
|
|
|
|
|
|
mc.guid = createFishData.guid + i;
|
|
|
|
|
|
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
|
|
|
|
|
|
|
|
|
|
|
|
fishDatas_hashCodekey[mc.guid] = mc;
|
|
|
|
|
|
fishDatas_hashCodekey_Small[mc.guid] = mc;
|
|
|
|
|
|
|
|
|
|
|
|
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 环形阵:在同一路径上生成 count 条鱼,角度均匀分布(360/count)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Quan(FrameData_CreateFish createFishData, FishArrayConfig yz,
|
|
|
|
|
|
Vector3 pos, GameObject prefab, int pathId, int count, long time)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (count <= 0) return;
|
|
|
|
|
|
var cfg = spawnDic[createFishData.fishNumber];
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
float angle = (360f / count) * i;
|
|
|
|
|
|
var rotation = Quaternion.Euler(
|
|
|
|
|
|
prefab.transform.eulerAngles + Vector3.forward * angle);
|
|
|
|
|
|
|
2026-04-29 23:53:55 +08:00
|
|
|
|
//var fish = Instantiate(prefab, pos, rotation, fishRoot);
|
|
|
|
|
|
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, rotation, fishRoot);
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var mc = fish.GetComponent<MonsterContral>();
|
|
|
|
|
|
|
|
|
|
|
|
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
|
|
|
|
|
|
mc.guid = createFishData.guid + i;
|
|
|
|
|
|
mc.moveTime = (BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f;
|
|
|
|
|
|
|
|
|
|
|
|
fishDatas_hashCodekey[mc.guid] = mc;
|
|
|
|
|
|
fishDatas_hashCodekey_Small[mc.guid] = mc;
|
|
|
|
|
|
|
|
|
|
|
|
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 顺序阵:每隔 1s 生成一条鱼,共生成 count 条。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private IEnumerator YZ7007(FrameData_CreateFish createFishData, FishArrayConfig yz,
|
|
|
|
|
|
Vector3 pos, GameObject prefab, int pathId, long time, int count)
|
|
|
|
|
|
{
|
|
|
|
|
|
var cfg = spawnDic[createFishData.fishNumber];
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
2026-04-29 23:53:55 +08:00
|
|
|
|
//var fish = Instantiate(prefab, pos, prefab.transform.rotation, fishRoot);
|
|
|
|
|
|
var fish = Pool.Instance.Get(int.Parse(yz.fishNumber), pos, Quaternion.identity, fishRoot);
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var mc = fish.GetComponent<MonsterContral>() ?? fish.AddComponent<MonsterContral>();
|
|
|
|
|
|
|
|
|
|
|
|
mc.monsterData.fishTypeConfig = FishDatas[yz.fishNumber];
|
|
|
|
|
|
mc.guid = createFishData.guid + i;
|
|
|
|
|
|
// 每条鱼额外减去已等待秒数,使路径起点与帧数同步
|
|
|
|
|
|
mc.moveTime = ((BeijingTimeManager.Instance.CurrentTimestampMs - time) / 1000f) - i;
|
|
|
|
|
|
|
|
|
|
|
|
fishDatas_hashCodekey[mc.guid] = mc;
|
|
|
|
|
|
fishDatas_hashCodekey_Small[mc.guid] = mc;
|
|
|
|
|
|
|
|
|
|
|
|
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
|
|
|
|
|
|
|
|
|
|
|
|
yield return new WaitForSeconds(1f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 随机工具方法
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从 [min, max) 区间随机取 count 个不重复整数。
|
|
|
|
|
|
/// 若 min==max 返回空列表。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static List<int> RandomUniqueNumbers(int count, int min, int max)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (min >= max)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("[CreateFishManager] RandomUniqueNumbers: min >= max,返回空列表");
|
|
|
|
|
|
return new List<int>();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
count = Mathf.Min(count, max - min); // 不能超过范围
|
|
|
|
|
|
var result = new HashSet<int>();
|
|
|
|
|
|
var rand = new System.Random();
|
|
|
|
|
|
|
|
|
|
|
|
while (result.Count < count)
|
|
|
|
|
|
result.Add(rand.Next(min, max));
|
|
|
|
|
|
|
|
|
|
|
|
return result.ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从 KeyCollection 中随机取 count 个不重复的 string key。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static List<string> RandomUniqueNumbers(int count, int min, int max,
|
|
|
|
|
|
Dictionary<string, List<RoomFishDetailConfig>>.KeyCollection keyCollection)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (min >= max) return new List<string>();
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
|
|
while (indices.Count < count)
|
|
|
|
|
|
{
|
|
|
|
|
|
int idx = rand.Next(min, max);
|
|
|
|
|
|
if (indices.Add(idx))
|
|
|
|
|
|
result.Add(keyList[idx]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 杀鱼接口
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 随机选取 count 条小鱼/黄金鱼,通知服务器同步死亡,并返回 guid 列表。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public List<string> SyncGameData_SendRendromDieFishID(
|
|
|
|
|
|
int count, List<RedPacketRecord> coinNum, Vector3 v3Point)
|
|
|
|
|
|
{
|
|
|
|
|
|
var guids = new List<string>(count);
|
|
|
|
|
|
var tempKeys = fishDatas_hashCodekey_Small.Keys.ToList();
|
|
|
|
|
|
|
|
|
|
|
|
// 若存活鱼不足 count,全部选取
|
|
|
|
|
|
if (tempKeys.Count <= count)
|
|
|
|
|
|
{
|
|
|
|
|
|
guids.AddRange(tempKeys);
|
2026-04-23 17:24:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
int idx = Random.Range(0, tempKeys.Count);
|
|
|
|
|
|
guids.Add(tempKeys[idx]);
|
|
|
|
|
|
tempKeys.RemoveAt(idx);
|
2026-04-23 17:24:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
int posID = currGameType.currSitData.posID;
|
|
|
|
|
|
var sgd = new SyncGameData
|
2026-04-23 17:24:31 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
sitPos = posID,
|
|
|
|
|
|
frameType = FrameDataType.randomDieFish,
|
|
|
|
|
|
time = BeijingTimeManager.Instance.CurrentTimestampMs,
|
|
|
|
|
|
frameData = new FrameData_RandomDieFish
|
2026-04-23 17:24:31 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
x = v3Point.x,
|
|
|
|
|
|
y = v3Point.y,
|
|
|
|
|
|
z = v3Point.z,
|
|
|
|
|
|
guids = guids,
|
|
|
|
|
|
coinNum = coinNum,
|
|
|
|
|
|
count = count
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-04-23 17:24:31 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
WebSocketSendList.SyncGameData(sgd);
|
|
|
|
|
|
return guids;
|
2026-04-23 17:24:31 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 按 ID 杀死一条鱼(无特效版)。
|
|
|
|
|
|
/// </summary>
|
2026-04-22 16:22:28 +08:00
|
|
|
|
public void Id_DieFish_NotFX(string fishId)
|
2026-03-31 17:00:05 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (!fishDatas_hashCodekey.TryGetValue(fishId, out var monster)) return;
|
|
|
|
|
|
|
|
|
|
|
|
monster.DieFish();
|
|
|
|
|
|
fishDatas_hashCodekey.Remove(fishId);
|
2026-04-03 18:32:19 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 按 ID 杀死一条鱼(带特效 + 金币飞出动画)。
|
|
|
|
|
|
/// </summary>
|
2026-04-25 18:53:04 +08:00
|
|
|
|
public void Id_DieFish_FX(string fishId, RedPacketRecord coinNum, Vector3 v3Point)
|
2026-04-22 18:15:22 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (!fishDatas_hashCodekey.TryGetValue(fishId, out var monster)) return;
|
|
|
|
|
|
|
|
|
|
|
|
AudioManager.Instance.PlayerFX(60004);
|
|
|
|
|
|
|
|
|
|
|
|
// 死亡粒子特效
|
|
|
|
|
|
Instantiate(
|
|
|
|
|
|
monster.effect_Die != null ? monster.effect_Die : dieFXPrefab,
|
|
|
|
|
|
monster.transform.position, Quaternion.identity, transform.parent);
|
|
|
|
|
|
|
|
|
|
|
|
// 非 Boss 鱼:金币飞向炮台
|
|
|
|
|
|
if (monster.fishenum != FishTypeEnum.Boss鱼)
|
2026-04-22 18:15:22 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var award = Instantiate(
|
|
|
|
|
|
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAward,
|
|
|
|
|
|
currGameType.subPanelParent.parent);
|
2026-04-23 17:24:31 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
award.GetComponent<RectTransform>().anchoredPosition =
|
|
|
|
|
|
CoordinateTransformation.WorldPos_ToCanvas(
|
|
|
|
|
|
monster.transform.position,
|
|
|
|
|
|
UIManager.Instance.uiRoot.GetComponent<Canvas>());
|
2026-04-22 18:15:22 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
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.SetCoinCount(coinNum.Amount);
|
2026-04-22 18:15:22 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
MonsterDieList.Instance.SmallHuangYiHuang(
|
|
|
|
|
|
monster.transform.position,
|
|
|
|
|
|
monster.monsterData.fishTypeConfig.fishNumber, 1000);
|
|
|
|
|
|
|
|
|
|
|
|
monster.DieFish();
|
|
|
|
|
|
fishDatas_hashCodekey.Remove(fishId);
|
2026-04-22 18:15:22 +08:00
|
|
|
|
}
|
2026-04-22 23:08:46 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 批量杀死多条鱼(带特效)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Id_DieListFish_FX(List<string> ids, List<RedPacketRecord> coinNum, Vector3 v3Point)
|
2026-04-22 18:15:22 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
for (int i = 0; i < ids.Count; i++)
|
2026-04-25 18:53:04 +08:00
|
|
|
|
Id_DieFish_FX(ids[i], coinNum[i], v3Point);
|
2026-04-22 18:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 收到服务器 WebSocket 杀鱼通知,处理金币加分、特效、音效。
|
|
|
|
|
|
/// </summary>
|
2026-03-31 17:00:05 +08:00
|
|
|
|
public void Ws_DieFish(string msg)
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var killFish = JsonConvert.DeserializeObject<WebSocketResponseBase<RoomKillNotice>>(msg)
|
|
|
|
|
|
.arguments[0];
|
2026-04-25 18:53:04 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
Debug.Log($"[CreateFishManager] 杀鱼延迟:{DateTimeOffset.Now.ToUnixTimeSeconds() - killFish.timespan}s");
|
|
|
|
|
|
|
|
|
|
|
|
if (!fishDatas_hashCodekey.TryGetValue(killFish.fishId, out var monster)) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 加分回调(在金币飞完后执行)
|
|
|
|
|
|
Action<int> onScoreAdd = audioID =>
|
2026-04-25 18:53:04 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var sitList = GetCurrentPanelSitList();
|
|
|
|
|
|
if (sitList != null)
|
2026-04-28 01:53:41 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
foreach (var sit in sitList)
|
2026-04-28 01:53:41 +08:00
|
|
|
|
{
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (sit.user != null && sit.user == killFish.userId)
|
|
|
|
|
|
sit.goldNum += killFish.gold;
|
2026-04-28 01:53:41 +08:00
|
|
|
|
}
|
2026-04-25 18:53:04 +08:00
|
|
|
|
}
|
2026-04-29 01:18:39 +08:00
|
|
|
|
AudioManager.Instance.PlayerFX(audioID);
|
|
|
|
|
|
};
|
2026-04-25 18:53:04 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
// 死亡粒子特效
|
|
|
|
|
|
Instantiate(
|
|
|
|
|
|
monster.effect_Die != null ? monster.effect_Die : dieFXPrefab,
|
|
|
|
|
|
monster.transform.position, Quaternion.identity, transform.parent);
|
2026-04-25 18:53:04 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
if (monster.fishenum != FishTypeEnum.Boss鱼)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 普通鱼:金币飞向炮台
|
|
|
|
|
|
var award = Instantiate(
|
|
|
|
|
|
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAward,
|
|
|
|
|
|
currGameType.subPanelParent.parent);
|
2026-04-25 18:53:04 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
award.GetComponent<RectTransform>().anchoredPosition =
|
|
|
|
|
|
CoordinateTransformation.WorldPos_ToCanvas(
|
|
|
|
|
|
monster.transform.position,
|
|
|
|
|
|
UIManager.Instance.uiRoot.GetComponent<Canvas>());
|
2026-04-25 18:53:04 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
var coinScript = award.GetComponent<CoinScript>();
|
|
|
|
|
|
coinScript.endPoint = currGameType.currSitData.transform;
|
|
|
|
|
|
coinScript.isBoss = false;
|
|
|
|
|
|
coinScript.SetCoinCount(killFish.gold);
|
|
|
|
|
|
coinScript.JiaFen = onScoreAdd;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Boss 鱼:显示浮动分数文本
|
|
|
|
|
|
var bossCtrl = (MonsterControl_BossBase)monster;
|
|
|
|
|
|
bossCtrl.tMP_CurrBossScore = Instantiate(
|
|
|
|
|
|
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAwardTmp,
|
|
|
|
|
|
currGameType.subPanelParent.parent)
|
|
|
|
|
|
.transform.GetChild(0).GetComponent<TextMeshProUGUI>();
|
|
|
|
|
|
bossCtrl.JiaFen = onScoreAdd;
|
|
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2026-04-29 01:18:39 +08:00
|
|
|
|
MonsterDieList.Instance.SmallHuangYiHuang(
|
|
|
|
|
|
monster.transform.position,
|
|
|
|
|
|
monster.monsterData.fishTypeConfig.fishNumber, 1000);
|
|
|
|
|
|
|
|
|
|
|
|
monster.DieFish(killFish);
|
|
|
|
|
|
fishDatas_hashCodekey.Remove(killFish.fishId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
// 工具:获取当前面板座位列表
|
|
|
|
|
|
// ================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据当前游戏类型返回对应 UI 面板的座位列表。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private List<SitPosData> GetCurrentPanelSitList()
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (GameManager.Instance.gameData.currGameType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case GameType.defaultPanel:
|
|
|
|
|
|
return UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelDefault).list_Sits;
|
|
|
|
|
|
case GameType.FLZY:
|
|
|
|
|
|
return UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelFLZY).list_Sits;
|
|
|
|
|
|
case GameType.TGXX:
|
|
|
|
|
|
return UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelTGXX).list_Sits;
|
|
|
|
|
|
case GameType.XJMH:
|
|
|
|
|
|
return UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelXJMH).list_Sits;
|
|
|
|
|
|
case GameType.HHWK:
|
|
|
|
|
|
return UIManager.Instance.Get<GameMainPanel_FishBase>(UIPanel.MainGamePanelHHWK).list_Sits;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return null;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|