特效处理

This commit is contained in:
2026-10-20 18:30:03 +08:00
parent 40bd235e67
commit bee2d42356
131 changed files with 837 additions and 456 deletions
@@ -332,6 +332,9 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ⭐ 鱼创建改由服务端 OnFishSpawn 事件统一下发,客户端不再监听 createFish 帧同步
EventCenter.Instance.AddEventListener<OnFishSpawnData>(
ConstEventString.OnFishSpawn, OnFishSpawn);
// ⭐ 重连/挂起恢复:服务端全量重同步活鱼,客户端全量替换本地鱼
EventCenter.Instance.AddEventListener<OnFishResyncData>(
ConstEventString.OnFishResync, OnFishResync);
// ⭐ 注入红包网络发送回调给框架层 LayeredPool(框架层不再反向依赖 CreateFishManager)
LayeredPool.OnSendRandomDieFishID = (c, r, p, s) => SyncGameData_SendRendromDieFishID(c, r, p, s);
@@ -389,6 +392,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
{
EventCenter.Instance.RemoveEventListener<OnFishSpawnData>(
ConstEventString.OnFishSpawn, OnFishSpawn);
EventCenter.Instance.RemoveEventListener<OnFishResyncData>(
ConstEventString.OnFishResync, OnFishResync);
// 释放 NativeArray,避免内存泄漏
DisposeNativeArrays();
@@ -775,6 +780,97 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
NetLog.Log($"[CreateFishManager] OnFishSpawn type={data.type}, count={data.fish.Count}, batched={batchedQueue.Count}");
}
// ================================================================
// 全量重同步活鱼 OnFishResync(重连 / 挂起恢复)
// ================================================================
/// <summary>
/// 服务端全量重同步活鱼处理。语义为"全量替换":
/// ① 清空本地残留鱼(只清鱼实例与事件级去重记录,不动 spawnDic/鱼配置)
/// ② 复用 OnFishSpawn 链路重建(type="sync" → spawnTime=createdAt,鱼落在路径正确位置)
/// fish 为空列表同样要走清空(服务端此刻场上确实没鱼,客户端必须把残留清掉)。
/// ⭐ 三个必须处理的要点(天真实现会踩坑):
/// 1. 加载期(spawnDic==null)不能丢事件:必须先转成 OnFishSpawnData 再入队——
/// 队列类型是 List&lt;OnFishSpawnData&gt;,直接塞 OnFishResyncData 编译不过;
/// 入队时顺带丢弃队列里更早的出鱼事件,避免"旧事件先建鱼→resync 再清空"的多余抖动
/// 2. 冰冻中必须整段跳过:OnFishSpawn 开头 isFrozen 直接 return,
/// 若先清空会一条都建不回来 → 空场
/// 3. 不能指望 OnFishSpawn 的空列表分支来清空:它开头 `fish==null||Count==0 → return`,
/// 空列表压根到不了后面的逻辑,所以清空必须在调用它之前独立完成
/// ⚠️ 全量替换会销毁并重建所有鱼:正被锁定/正在播受击、爆奖动画的鱼会被打断,
/// 重连瞬间可能闪一下。若要避免,需改成"按 fishId 差集"只销毁服务端列表里没有的鱼。
/// </summary>
public void OnFishResync(OnFishResyncData data)
{
if (data == null) return;
int fishCount = data.fish != null ? data.fish.Count : 0;
// ⭐ 加载期:转成出鱼事件入队,EnterRoom 末尾回放
// (同时清掉队列里更早的事件:重连场景下那些旧房间残留的 init/spawn 不该再回放)
if (spawnDic == null)
{
_pendingFishSpawns = new List<OnFishSpawnData> { BuildSyncSpawnData(data) };
Debug.Log($"[CreateFishManager] 生成系统未就绪,重同步事件入队等待回放: count={fishCount}");
return;
}
// ⭐ 冰冻中跳过整个流程:清空后建不回来会空场
if (isFrozen)
{
Debug.Log("[CreateFishManager] 冰冻中,跳过重同步(避免清空后建不回来)");
return;
}
// ① 清空本地残留鱼
int cleared = ClearAllFishes();
// ② 复用出鱼链路重建
var syncData = BuildSyncSpawnData(data);
if (fishCount > 0) OnFishSpawn(syncData);
Debug.Log($"[CreateFishManager] 重同步完成: 清空{cleared}条, 重建{fishCount}条");
}
/// <summary>
/// OnFishResyncData → OnFishSpawnData。
/// type 固定 "sync":让 spawnTime 取 createdAt,鱼落在路径上的正确位置(否则全部回到起点)。
/// </summary>
private static OnFishSpawnData BuildSyncSpawnData(OnFishResyncData data)
{
return new OnFishSpawnData
{
type = "sync",
timestamp = data.timestamp,
fish = data.fish
};
}
/// <summary>
/// 全量清空场上本地鱼(重同步用)。只清鱼实例与事件级去重记录,不动配置(spawnDic/fishDatas)。
/// ⭐ 先快照 key 再逐个 Id_DieFish_NotFX:该方法内部会按鱼类型从各分类字典移除并回池,
/// 直接遍历 fishDatas_hashCodekey 会抛 InvalidOperationException。
/// ⭐ 末尾必须清 _handledFishIds:重同步会用同一批 fishId 重建,
/// 不清会被 15 秒窗口判成"重复出鱼已跳过"→ 一条都建不出来。
/// </summary>
private int ClearAllFishes()
{
int cleared = 0;
if (fishDatas_hashCodekey != null && fishDatas_hashCodekey.Count > 0)
{
var guids = new List<string>(fishDatas_hashCodekey.Keys);
foreach (var guid in guids)
{
if (string.IsNullOrEmpty(guid)) continue;
Id_DieFish_NotFX(guid);
cleared++;
}
}
_handledFishIds.Clear();
return cleared;
}
/// <summary>生成系统未就绪期间收到的出鱼事件队列(EnterRoom 完成后回放)</summary>
private List<OnFishSpawnData> _pendingFishSpawns;