如何在Timeline中让某轨道忽略timeScale
解读
国内项目普遍用 Timeline 做剧情、技能、UI 动效,策划经常要求“暂停按钮不能把演出全停掉”,本质就是部分轨道要无视 Time.timeScale。如果候选人只答“把 timeScale 改回 1”会被直接判负,因为那会破坏全局暂停逻辑;正确思路是让轨道自己驱动时间,而不是依赖 Unity 的全局时间。面试官想听你能否在不改引擎源码的前提下,用官方开放接口把“轨道时间”和“游戏时间”解耦,并兼顾编辑器预览、运行时热更、移动端性能。
知识点
- PlayableGraph 的 UpdateMode:DSP、GameTime、UnscaledGameTime、Manual
- TrackAsset 的 CreateTrackMixer 返回自定义 PlayableBehaviour,可重写 PrepareFrame 或 ProcessFrame
- Playable.GetTime 与 SetTime 是轨道内部时间,Director.time 受 timeScale 影响
- IPlayableBehaviour.GetMixerTime 可拿到 Director 的 unscaled 时间:
var unscaled = (float)playable.GetGraph().GetResolver().GetTimeUpdateMode() == DirectorUpdateMode.Manual ? Time.unscaledTime : Director.time / Time.timeScale * Time.unscaledTime; - 自定义 Clip PlayableBehaviour 里缓存进入时的 unscaledTime,后续帧用
Time.unscaledTime - enterTime做本地时钟 - Build 时打宏
#if UNITY_EDITOR区分编辑器预览与真机,防止编辑器下误用 unscaledTime 导致 scrub 失效 - 热更框架(HybridCLR/ILRuntime) 下,自定义 PlayableBehaviour 必须生成绑定代码,否则裁剪后反射找不到类型
答案
- 新建一个 IgnoreTimeScaleTrack 继承 TrackAsset,重写
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
返回自定义 IgnoreTimeScaleMixerBehaviour。 - IgnoreTimeScaleMixerBehaviour 实现 IPlayableBehaviour:
- 在 PrepareFrame 里用
Time.unscaledTime计算本地时钟m_UnscaledTime - 遍历所有 input clip,调用
playable.GetInput(i).SetTime(m_UnscaledTime),把本地时间写进每个 clip 的 playable - 返回 true,告诉 graph 使用自定义时间
- 在 PrepareFrame 里用
- 对 clip 端,如果自带动画(AnimationPlayable),在 ProcessFrame 里把权重设为 1,强制采样
animationPlayable.SetTime(m_UnscaledTime) - 把轨道上的 UpdateMode 设为 DSP 或 Manual,防止 Director 的 deltaTime 被 timeScale 缩放
- 真机测试:在 Update 里临时把 timeScale 设为 0,确认角色特效、UI 粒子继续播放;Profiler 中观察 PlayableGraph.Evaluate 耗时,确保移动端 < 0.3 ms
一句话总结:在 TrackMixer 里用 Time.unscaledTime 重写 playable 的本地时间,完全绕开 Director 的 timeScale
拓展思考
- 部分忽略需求:如果只想忽略 50% 的 timeScale,可在 PrepareFrame 里做
lerp(Director.time, unscaledTime, weight),让策划在 Timeline 窗口直接调曲线 - 网络帧同步:在帧同步战斗里,服务器发帧号,客户端把帧号转成 unscaledTime,保证技能 Timeline 在断网暂停时继续走完收刀动作
- 音频轨道:AudioTrack 内部用 FMOD,不受 timeScale 影响,但若用 AudioMixer 做快照,需要把 AudioSource.pitch 同步到 1/timeScale,否则会出现音画不同步
- WebGL 限制:WebGL 的 Time.unscaledTime 精度只有 1 ms,高频演出需改用 AudioSettings.dspTime 做主时钟,否则 120 fps 下会出现抖动