This commit is contained in:
2026-09-15 22:38:11 +08:00
parent a1a4beac5b
commit e709a4a7ab
6 changed files with 197 additions and 32 deletions
@@ -415,6 +415,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
InitSpawnSystem(gameType);
BindCurrentGamePanel();
EnsureBJEffectRoot();
// ⭐ 回放进房加载期间收到的出鱼事件(服务端进房瞬间推的 init/sync 初始鱼)
FlushPendingFishSpawns();
}
/// <summary>
@@ -665,11 +667,21 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
{
if (data == null || data.fish == null || data.fish.Count == 0) return;
if (isFrozen) return; // 冰冻中不创建鱼
if (spawnDic == null) return; // 场景卸载后忽略
// ⭐ 修复:生成系统未就绪(进房加载中/退房清理后 spawnDic==null)时不再丢弃事件,
// 先入队,EnterRoom 完成后回放。服务端在进房瞬间就会推 OnFishSpawn(init/sync)初始鱼,
// 而此时客户端还在 LoadResources 加载(数秒),直接 return 会把初始鱼全部丢掉 → 进房不出鱼。
if (spawnDic == null)
{
if (_pendingFishSpawns == null) _pendingFishSpawns = new List<OnFishSpawnData>();
_pendingFishSpawns.Add(data);
Debug.Log($"[CreateFishManager] 生成系统未就绪,出鱼事件入队等待回放: type={data.type}, count={data.fish.Count}, queued={_pendingFishSpawns.Count}");
return;
}
// ⭐ 分帧出鱼:普通鱼/黄金鱼分批生成(每帧5条),其他类型立即全出
// 避免一次出大量普通鱼导致单帧卡顿
var batchedQueue = new List<OnFishSpawnFishItem>(data.fish.Count);
bool isSync = data.type == "sync";
foreach (var item in data.fish)
{
@@ -685,19 +697,39 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
else
{
// Boss/特殊鱼/鱼阵等:立即生成
TrySpawnSingleFish(item);
TrySpawnSingleFish(item, isSync);
}
}
// 分帧组:启动协程逐帧生成
if (batchedQueue.Count > 0)
{
StartCoroutine(SpawnFishBatchedCoroutine(batchedQueue));
StartCoroutine(SpawnFishBatchedCoroutine(batchedQueue, isSync));
}
NetLog.Log($"[CreateFishManager] OnFishSpawn type={data.type}, count={data.fish.Count}, batched={batchedQueue.Count}");
}
/// <summary>生成系统未就绪期间收到的出鱼事件队列(EnterRoom 完成后回放)</summary>
private List<OnFishSpawnData> _pendingFishSpawns;
/// <summary>
/// 回放进房加载期间收到的出鱼事件(服务端在进房瞬间推的 init/sync 初始鱼)。
/// 在 EnterRoom 末尾调用:此时配置/资源/面板都已就绪。
/// </summary>
private void FlushPendingFishSpawns()
{
if (_pendingFishSpawns == null || _pendingFishSpawns.Count == 0) return;
var queue = _pendingFishSpawns;
_pendingFishSpawns = null; // 先置空,回放期间新到事件走正常路径
Debug.Log($"[CreateFishManager] 回放加载期间出鱼事件: {queue.Count} 批");
foreach (var data in queue)
{
try { OnFishSpawn(data); }
catch (System.Exception e) { Debug.LogWarning($"[CreateFishManager] 回放出鱼事件失败: {e.Message}"); }
}
}
/// <summary>
/// 判断该鱼是否需要分帧生成。
/// 普通鱼(1)和黄金鱼(3)且非鱼阵 → 分帧;其他(Boss/特殊鱼/特殊Boss/鱼阵) → 立即出。
@@ -722,7 +754,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>
/// 分帧出鱼协程:每帧生成 batchSize 条,避免单帧卡顿。
/// </summary>
private IEnumerator SpawnFishBatchedCoroutine(List<OnFishSpawnFishItem> queue)
private IEnumerator SpawnFishBatchedCoroutine(List<OnFishSpawnFishItem> queue, bool isSync)
{
const int batchSize = 5; // 每帧生成5条
int index = 0;
@@ -734,7 +766,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
int end = Mathf.Min(index + batchSize, queue.Count);
for (int i = index; i < end; i++)
{
TrySpawnSingleFish(queue[i]);
TrySpawnSingleFish(queue[i], isSync);
}
index = end;
yield return null; // 等待下一帧
@@ -744,7 +776,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
/// <summary>
/// 尝试生成单条鱼(含去重检查)。返回是否成功生成。
/// </summary>
private bool TrySpawnSingleFish(OnFishSpawnFishItem item)
private bool TrySpawnSingleFish(OnFishSpawnFishItem item, bool isSync = false)
{
if (item == null) return false;
@@ -791,9 +823,10 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
// ⭐ 根据 type 决定 moveTime:
// - spawn/init:新鱼,传当前时间 → moveTime≈0,鱼从曲线起点开始游
// (避免服务端/客户端时间差导致 moveTime>0,鱼瞬间出现在曲线中间)
// (避免服务端/客户端时间差或事件排队回放延迟导致 moveTime>0,
// 鱼凭空出现在曲线中间甚至已过路径末端)
// - sync:同步已有鱼,传 createdAt → moveTime=时间差,鱼出现在路径正确位置
long spawnTime = item.createdAt;
long spawnTime = isSync ? item.createdAt : BeijingTimeManager.Instance.CurrentTimestampMs;
SpawnFishMainThread(createFishData, spawnTime);
return true;
@@ -1273,6 +1306,8 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
//await Task.Delay(2000);
spawnList = null;
spawnDic = null;
// ⭐ 退房清理排队中的出鱼事件,防止旧房间残留鱼泄进下一个房间
if (_pendingFishSpawns != null) _pendingFishSpawns.Clear();
yz_FishConfig_Line_Dic = null;
yz_FishConfig_Line = null;
yz_FishConfig_Line_Dic1 = null;