性能分析与调试

Texturge 是 CPU 驱动的动画求值系统。21 通道逐字形逐图层曲线求值构成主要开销。理解热点路径与性能模型有助于在高负载场景保持帧率。

性能模型

曲线求值成本估算

每帧的动画求值开销近似为:

总求值次数 ≈ 字形数 × 图层数 × 非空通道数(≤21)

典型场景示例:

场景字形数图层数每帧非空通道求值(估)
简单打字机501~1,050
多图层标题303~3,000
富文本对话1003~10,000

实际开销远低于公式上限,因为:

  1. 空通道跳过——FPerLayerCurves::Evaluate 仅对 NumKeys > 0 的通道求值
  2. 静态字形跳过——bIsStatic 字形直接返回 DefaultState,零曲线求值
  3. 尚未开始 / 已结束字形——HasStarted / HasFinished 提前退出

热点路径

FBakedGlyph::Evaluate 是动画求值的核心热点:

  1. bIsStatic → 返回 DefaultState(零开销)
  2. LocalTime < 0(未开始)→ 返回恒等状态(仅 bHideFirstFrame 时透明)
  3. 遍历 LayerCurves,调用 FPerLayerCurves::Evaluate
  4. FPerLayerCurves::Evaluate 对非空通道:临时构建 FRichCurveBuildRichCurveFromKeys)→ Eval(LocalTime) → 按 BlendMode 组合

性能关键点

  • 曲线键在编译期预烘焙为 TArray<FRichCurveKey>,运行时无曲线解析开销
  • BuildRichCurveFromKeys 每次求值构建临时 FRichCurve——大文本 + 多层时可累积(已知技术限制,未来优化方向:缓存 + 脏位或直接对排序 keys 二分搜索)
  • 编译在需要时完成,运行时零烘焙开销

Unreal Insights 通用分析

Texturge 未注册自定义 Trace 通道与控制台统计命令,使用 Unreal Insights 的通用 CPU 采样分析:

  1. 启动 Trace 录制(控制台 Trace.Start,或 Unreal Insights 会话启动)
  2. 运行动画场景至少 5 秒收集样本
  3. Trace.Stop 停止,在 Insights 中打开 .utrace
  4. CPU 时间线放大动画播放时段,定位 UTextAnimationStageController::TickAnimationFPerLayerCurves::Evaluate、Slate OnPaint 的调用栈占比

分析优先级

  1. 检查 TickAnimation 总耗时占比;超过 2ms/帧需深入
  2. 展开求值调用栈,确认是否因字形数 × 图层数过大导致
  3. OnPaint 耗时高时,检查是否同时渲染大量 UAnimatedTextBlock 控件(合批问题,见《性能最佳实践》)

指纹缓存

机制

FAnimationCompiler 使用 CityHash64 计算双指纹(uint64):

指纹计算内容缓存命中条件
TextFingerprintCityHash64(SourceText)文本未变化
BlueprintFingerprint路径 + 所有 GlyphAnimation 资产签名(MovieScene + Track/Section GetSignature())+ BlueprintVisible CDO 属性值 + StageTransitionConfig + CompileCount + GeneratedClass 地址蓝图未编译、参数未变化

缓存失效时机

  • 文本内容改变 → 文本指纹变化 → 触发重新烘焙
  • Sequencer 中编辑 UGlyphAnimation 曲线 → Section 签名变化 → 蓝图指纹变化
  • 蓝图编译(含变量修改)→ CompileCount 递增 → 指纹变化
  • SetBlueprintVariable 参数修改 → CDO 属性值变化 → 指纹变化

重烘焙冷却

MinFramesBetweenRebakes = 3——参数扫频(如逐帧修改变量)时,最多 3 帧延迟生效,防止洪水重烘焙。缓存失效决策在控件层 / 编辑器预览层(FTexturgePreviewBakeCache),编译期不负责刷新策略。

数据规模建议

规模建议
每控件字形数≤ 500(单行文本常规规模);超长文本拆分多控件
每字形图层数2~4 层足够绝大多数效果(预设库默认 ≤ 3 层)
同屏动画控件≤ 8 个富文本路径控件(多条目同时播放开销大)
循环动画使用层 NumberOfLoops 或控制器循环,避免逐帧重建

TIP

性能优化优先顺序:减少字形数(SkipAt 跳过空白)→ 减少图层数 → 减少非空通道数(删除未使用轨道)→ 合批控件。

images/insights-profiling.png — Unreal Insights 性能分析截图:CPU 时间线中定位 UTextAnimationStageController::TickAnimation 与 Slate OnPaint 调用栈,下方帧时间柱状图标注动画播放阶段的峰值 — Unreal Insights profiling screenshot: CPU timeline locating UTextAnimationStageController::TickAnimation and Slate OnPaint call stacks, frame time histogram below marking the peak during animation playback