1
This commit is contained in:
@@ -223,6 +223,18 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
public float currBingFengTime = 0f;
|
||||
private Dictionary<Component, object> _frozenAnimSpeeds = new Dictionary<Component, object>();
|
||||
|
||||
/// <summary>
|
||||
/// 冰冻中“受 Timeline 驱动”的 Animator(其所属鱼体内存在 PlayableDirector)。
|
||||
/// ⭐ 这些 Animator 的动画由 Timeline 驱动,冰冻时绝对不能把 speed 设 0:
|
||||
/// speed=0 会让 Timeline 的动画输出失效 → 模型瞬间回退到默认姿态。
|
||||
/// 它们的定格交给 director(根 Playable 速度归零)处理。
|
||||
/// </summary>
|
||||
private readonly HashSet<Animator> _timelineDrivenAnimators = new HashSet<Animator>();
|
||||
|
||||
/// <summary>冰冻中被定格的 Timeline:记录根 Playable 的原始速度,解冻时还原</summary>
|
||||
private readonly Dictionary<UnityEngine.Playables.PlayableDirector, double> _frozenDirectors
|
||||
= new Dictionary<UnityEngine.Playables.PlayableDirector, double>();
|
||||
|
||||
// ⭐ 暴走/冰封本地数量:因为暂无扣减 API,激活时本地 -1,避免被 OnUserDataChanged 覆盖回服务端旧值
|
||||
private int _localBaoZouCount = -1; // -1 表示尚未初始化
|
||||
private int _localBingFengCount = -1;
|
||||
@@ -947,6 +959,8 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
_bingFengInstance = null;
|
||||
}
|
||||
_frozenAnimSpeeds.Clear();
|
||||
// ⭐ 冰冻中面板被销毁(例如切房):把被定格的 Timeline 速度还原,避免残留 0 速导致时间轴永远不动
|
||||
RestoreFrozenDirectors();
|
||||
|
||||
}
|
||||
public virtual void Start()
|
||||
@@ -4672,11 +4686,15 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
// ⭐ 守卫:已暂停时直接返回,避免重复调用覆盖已记录的速度
|
||||
// (其他客户端会先后被 OnUsePropNotice 和 SyncGameData_FreezeFish 触发两次,
|
||||
// 第二次会记录 speed=0,解冻时恢复成 0 → 动画永远暂停)
|
||||
if (_frozenAnimSpeeds.Count > 0) return;
|
||||
if (_frozenAnimSpeeds.Count > 0 || _frozenDirectors.Count > 0) return;
|
||||
|
||||
var root = CreateFishManager.Instance.fishRoot;
|
||||
if (root == null) return;
|
||||
_frozenAnimSpeeds.Clear();
|
||||
_frozenDirectors.Clear();
|
||||
|
||||
// ⭐ 先收集“受 Timeline 驱动”的 Animator:它们必须跳过 speed=0 的处理
|
||||
CollectTimelineDrivenAnimators(root);
|
||||
|
||||
foreach (var s in root.GetComponentsInChildren<Spine.Unity.SkeletonAnimation>(true))
|
||||
{
|
||||
@@ -4687,6 +4705,9 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
foreach (var a in root.GetComponentsInChildren<Animator>(true))
|
||||
{
|
||||
if (!a.gameObject.activeInHierarchy) continue;
|
||||
// ⭐ Timeline 驱动的 Animator 不能设 speed=0:会让 Timeline 动画输出失效 →
|
||||
// 模型回退到默认姿态(雷霆之主冰冻后显示默认状态的根因)。由下面的 director 定格
|
||||
if (_timelineDrivenAnimators.Contains(a)) continue;
|
||||
_frozenAnimSpeeds[a] = a.speed;
|
||||
a.speed = 0f;
|
||||
}
|
||||
@@ -4704,14 +4725,56 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
}
|
||||
foreach (var pd in root.GetComponentsInChildren<UnityEngine.Playables.PlayableDirector>(true))
|
||||
{
|
||||
if (!pd.gameObject.activeInHierarchy || pd.state != PlayState.Playing) continue;
|
||||
_frozenAnimSpeeds[pd] = 1f;
|
||||
pd.Pause();
|
||||
if (!pd.gameObject.activeInHierarchy || pd.playableAsset == null) continue;
|
||||
|
||||
// ⭐ Timeline 鱼/Boss(雷霆之主 4052 等)必须定格在“当前帧”:
|
||||
// ⛔ 不能用 pd.Pause() —— 暂停会把 Timeline 的动画输出交还给 Animator,
|
||||
// 模型会瞬间回退到默认姿态(而不是暂停那一刻的姿态),且 Evaluate 也救不回来。
|
||||
// ✅ 正确做法:保持 director 继续播放,只把根 Playable 的速度设为 0。
|
||||
// 图仍在每帧求值同一帧 → 姿态定格在暂停瞬间,动画输出始终不脱离 Timeline。
|
||||
var graph = pd.playableGraph;
|
||||
if (!graph.IsValid()) continue; // 未播放过/已 Stop(图已销毁)无法定格
|
||||
|
||||
int rootPlayableCount = graph.GetRootPlayableCount();
|
||||
_frozenDirectors[pd] = rootPlayableCount > 0 ? graph.GetRootPlayable(0).GetSpeed() : 1d;
|
||||
for (int i = 0; i < rootPlayableCount; i++)
|
||||
graph.GetRootPlayable(i).SetSpeed(0d);
|
||||
|
||||
// 立即用定格帧刷新一次(delta=0 只应用姿态,不推进时间)
|
||||
graph.Evaluate();
|
||||
}
|
||||
|
||||
Debug.Log($"[冰冻] 暂停动画完成:Animator定格={_frozenAnimSpeeds.Count} Timeline定格={_frozenDirectors.Count} " +
|
||||
$"Timeline驱动Animator(跳过speed=0)={_timelineDrivenAnimators.Count}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集“受 Timeline 驱动”的 Animator:所属鱼体(fishRoot 的直接子节点)内存在 PlayableDirector。
|
||||
/// 冰冻时这些 Animator 不能设 speed=0(见 PauseAllFishAnimations 注释),由 director 定格。
|
||||
/// </summary>
|
||||
private void CollectTimelineDrivenAnimators(Transform root)
|
||||
{
|
||||
_timelineDrivenAnimators.Clear();
|
||||
foreach (var pd in root.GetComponentsInChildren<UnityEngine.Playables.PlayableDirector>(true))
|
||||
{
|
||||
if (pd.playableAsset == null) continue;
|
||||
|
||||
// 找到该 director 所属的鱼节点;挂在 fishRoot 本身的不处理(避免波及全部鱼)
|
||||
Transform fish = pd.transform;
|
||||
while (fish != root && fish.parent != null && fish.parent != root)
|
||||
fish = fish.parent;
|
||||
if (fish == root || fish.parent != root) continue;
|
||||
|
||||
foreach (var a in fish.GetComponentsInChildren<Animator>(true))
|
||||
_timelineDrivenAnimators.Add(a);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResumeAllFishAnimations()
|
||||
{
|
||||
// ⭐ 先还原被定格的 Timeline(根 Playable 速度恢复),Timeline 从未暂停过,无需 Resume
|
||||
RestoreFrozenDirectors();
|
||||
|
||||
if (_frozenAnimSpeeds.Count == 0) return;
|
||||
|
||||
foreach (var kv in _frozenAnimSpeeds)
|
||||
@@ -4734,12 +4797,29 @@ public class GameMainPanel_FishBase : GameMainPanel_Base
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UnityEngine.Playables.PlayableDirector pd: pd.Resume(); break;
|
||||
}
|
||||
}
|
||||
_frozenAnimSpeeds.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 还原冰冻期间被定格的 Timeline:恢复根 Playable 的原始速度(重新开始推进)。
|
||||
/// </summary>
|
||||
private void RestoreFrozenDirectors()
|
||||
{
|
||||
foreach (var kv in _frozenDirectors)
|
||||
{
|
||||
var pd = kv.Key;
|
||||
if (pd == null) continue;
|
||||
var graph = pd.playableGraph;
|
||||
if (!graph.IsValid()) continue;
|
||||
for (int i = 0; i < graph.GetRootPlayableCount(); i++)
|
||||
graph.GetRootPlayable(i).SetSpeed(kv.Value);
|
||||
}
|
||||
_frozenDirectors.Clear();
|
||||
_timelineDrivenAnimators.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 玩家加入/退出(PlayerJoinModule)
|
||||
|
||||
Reference in New Issue
Block a user