特效处理
This commit is contained in:
@@ -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<OnFishSpawnData>,直接塞 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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user