This commit is contained in:
2026-07-20 22:32:52 +08:00
parent 61b9b9a3e6
commit 9977ce1fc9
17 changed files with 254 additions and 109 deletions
@@ -240,6 +240,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
EventCenter.Instance.AddEventListener<SyncGameData>(
ConstEventString.SyncGameData_CreateFish, CreateFish);
// 监听新玩家"请求同步鱼"事件:房主收到后广播场上活鱼
EventCenter.Instance.AddEventListener<SyncGameData>(
ConstEventString.SyncGameData_RequestSyncFish, OnRequestSyncFish);
}
@@ -260,6 +264,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
{
EventCenter.Instance.RemoveEventListener<SyncGameData>(
ConstEventString.SyncGameData_CreateFish, CreateFish);
EventCenter.Instance.RemoveEventListener<SyncGameData>(
ConstEventString.SyncGameData_RequestSyncFish, OnRequestSyncFish);
// 释放 NativeArray,避免内存泄漏
DisposeNativeArrays();
@@ -1133,6 +1139,12 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
if (string.IsNullOrEmpty(mc.guid)) continue;
if (string.IsNullOrEmpty(mc.lastMoveLineId)) continue;
// ⭐ 跳过鱼阵鱼:鱼阵鱼 guid 是 原guid+i,单条广播会让新玩家收到后走
// SpawnFishArray 又生成 N 条,导致鱼阵指数爆炸(16×16=256)。
// 鱼阵鱼的同步需要鱼阵级别的广播(发鱼阵配置+原guid+数量),
// 这里不处理,鱼阵鱼不同步只影响视觉阵型,不影响游戏核心逻辑。
if (mc.isyz) continue;
// 总时长,用于过滤快死的鱼(避免新玩家刚进入就看到鱼死)
float totalTime = mc.monsterData.moveLine.moveTime;
if (totalTime <= 0f) continue;
@@ -1162,6 +1174,18 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
Debug.Log($"[CreateFishManager] 广播场上活鱼: {count} 条 (房主,新玩家加入同步)");
}
/// <summary>
/// 房主收到新玩家"请求同步鱼"事件后,广播场上活鱼。
/// 新玩家资源加载完成才会发请求,保证收到广播时 spawnDic 已初始化。
/// 非房主收到直接忽略。
/// </summary>
private void OnRequestSyncFish(SyncGameData syncGameData)
{
// 仅房主响应,且不响应自己发的请求(syncGameData.sitPos 是发送者座位)
if (!fangzhu) return;
BroadcastExistingFishes();
}
#endregion
#region 创建鱼
@@ -1175,8 +1199,17 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ⭐ 场景卸载/CloseSpawnSystem 后 spawnDic 会变 null,此时收到的广播直接忽略
if (spawnDic == null) return;
var rotateData = FrameDataParser.Parse<FrameData_CreateFish>(syncGameData.frameData);
if (rotateData != null)
SpawnFishMainThread(rotateData, syncGameData.time);
if (rotateData == null) return;
// ⭐ guid 去重:房主广播活鱼给新玩家时,服务器会广播给所有客户端(含房主自己)。
// 老玩家已存在该 guid 的鱼 → 跳过,避免重复 Spawn 同一条鱼。
// 仅本地无该 guid 的客户端(新加入玩家)才会真正 Spawn。
if (!string.IsNullOrEmpty(rotateData.guid) &&
fishDatas_hashCodekey != null &&
fishDatas_hashCodekey.ContainsKey(rotateData.guid))
return;
SpawnFishMainThread(rotateData, syncGameData.time);
}
/// <summary>
/// 主线程实例化鱼对象(单体鱼 / 鱼阵分发)。
@@ -1796,6 +1829,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// sitData.tMP_GoldNum.text = sitData.goldNum.ToString();
// AudioManager.Instance.PlayerFX(audioID);
//};
bool dieFishCalled = false; // Boss case 内部已调用 DieFish,底部跳过
switch (monster.fishenum)
{
@@ -1835,6 +1869,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
var bossCtrl = (MonsterControl_BossBase)monster;
bossCtrl.v3 = sitData.transform.position;
bossCtrl.JiaFen = onScoreAdd; // 先设置 JiaFen,DieFish 的 lambda 才能捕获到
monster.DieFish(killFish); // Boss 重写 action_effect_DieAward,捕获上面的 JiaFen
dieFishCalled = true;
if (bossCtrl.isToUI)
{
bossCtrl.currEffect_DieAward = Instantiate(
@@ -1847,7 +1885,6 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAwardTmp);
}
bossCtrl.action_effect_DieAward?.Invoke(bossCtrl.currEffect_DieAward);
bossCtrl.JiaFen = onScoreAdd;
}
@@ -1938,10 +1975,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
var bossCtrl = (MonsterControl_BossBase)monster;
bossCtrl.v3 = sitData.transform.position;
bossCtrl.JiaFen = onScoreAdd; // 先设置 JiaFen
monster.DieFish(killFish); // Boss 重写 action_effect_DieAward
dieFishCalled = true;
//bossCtrl.currEffect_DieAward = Instantiate(
// monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAwardTmp,
// currGameType.subPanelParent.parent);
if (bossCtrl.isToUI)
{
bossCtrl.currEffect_DieAward = Instantiate(
@@ -1954,14 +1991,14 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
monster.effect_DieAward != null ? monster.effect_DieAward : dieFXPrefabAwardTmp);
}
bossCtrl.action_effect_DieAward?.Invoke(bossCtrl.currEffect_DieAward);
bossCtrl.JiaFen = onScoreAdd;
}
break;
default:
break;
}
monster.DieFish(killFish);
if (!dieFishCalled)
monster.DieFish(killFish);
MonsterDieList.Instance.SmallHuangYiHuang(
monster.transform.position,
@@ -296,6 +296,30 @@ public class GameManager : MonoSingleton<GameManager>
WebSocketManager.Instance.Connect(SocketType.game, action);
});
}
/// <summary>
/// 快速加入:用 /api/Room/QuickJoin 返回的 url 直接连 game socket(无需再调 Assign)
/// </summary>
/// <param name="url">QuickJoin 返回的房间专属 socket 地址</param>
/// <param name="action">连接成功后的回调(一般是 JoinRoom(roomId, userId, -1))</param>
public void StartGameQuickJoin(string url, Action action)
{
switch (gameData.currGameType)
{
case GameType.FLZY:
case GameType.YYSC:
case GameType.XJMH:
case GameType.HHWK:
if (!string.IsNullOrEmpty(url))
WebSocketManager.Instance.Connect(SocketType.game, url, action);
else
WebSocketManager.Instance.Connect(SocketType.game, action);
break;
default:
WebSocketManager.Instance.Connect(SocketType.game, action);
break;
}
}
// Start is called before the first frame update
public Button btn_Skip;
public VideoClip startVideoClip;