Level Sequence Tips
Level Sequence Tips
TransformOriginActor
在 Unreal Engine 中,TransformOriginActor 是 Sequencer 的一个核心功能,用于实现动态位移(Dynamic Transforms)。
通常情况下,Sequencer 里的所有位移关键帧(Location/Rotation)都是基于世界坐标系(0, 0, 0)的。通过设置 TransformOriginActor,你可以让整个序列的动画变为相对于某个特定 Actor 的坐标系运行。
以下是关于该功能的核心概念、设置步骤及注意事项:
核心应用场景
- 重复利用动画:你制作了一个角色上车的动画,通过改变 Transform Origin Actor(将其设为不同的车辆),同一段动画可以在场景中任何位置的车辆上准确触发。
- 运行时动态定位:如果你的过场动画需要在玩家当前所在的位置播放,而不是在固定的地图坐标播放。
- 协同对齐:当角色需要与场景中的动态物体(如移动的平台或桌子)互动时,将物体设为原点可简化对位工作。
编辑器中的设置步骤
要为现有的 Level Sequence 设置变换原点:
- 在场景中选中 LevelSequenceActor(放置在世界中的序列实例)。
- 在 Details(细节) 面板中,找到 Sequence 栏目。
- 勾选 Override Instance Data(覆盖实例数据)。
- 在下方的 Transform Origin Actor 槽位中,选择场景中的某个 Actor。
此时,序列中所有的位移轨迹(Transform Tracks)都会以该 Actor 的坐标作为 (0,0,0) 进行偏移。
- 运行时通过 Blueprint (蓝图) 设置
如果你需要在游戏运行期间动态更改原点(例如在不同的 NPC 身上播放同一段处决动画),可以使用以下逻辑:
节点建议:使用 Set Transform Origin 或 Set Transform Origin Actor 节点。
流程:
- 获取 Level Sequence Actor 的引用。
- 调用 Get Sequence Player。
- 从 Player 引出 Set Transform Origin。
- 输入一个 Transform(坐标信息)或者一个 Actor。
注意:为了确保逻辑一致,建议在调用 Play 之前设置原点。
重要注意事项与最佳实践
- 先后顺序:建议先设置原点,后制作动画。如果你已经写好了世界坐标的关键帧,再去指定 Transform Origin Actor,你的角色/物体会发生位移(因为它们现在的坐标是相对于原点 Actor 的)。
- 消除位移偏移:如果你发现设置后位置不对,请检查原点 Actor 本身的旋转。序列会继承原点 Actor 的前向矢量(Forward Vector)。
- UE 5.5 新特性:在最新的 UE 5.5 中,现在支持在 Subsequences(子序列) 或 Shots(镜头) 上直接右键开启位移原点通道。这意味着你可以在一个大的序列里,为不同的片段指定不同的局部坐标原点,而无需多个 Level Sequence Actor。
性能与调试
- Eliminate(消除)误差:如果动画出现抖动,请确保原点 Actor 的移动是在 PrePhysics 阶段更新的,或者序列的更新步长与其同步。
- 可视化调试:你可以临时放置一个辅助轴(Arrow Component)作为 Transform Origin Actor,以便直观查看局部坐标系的朝向。
动态创建的 LevelSequenceActor 设置 TransformOrigin 无效,通常是因为设置时机太晚或缺少实例数据覆写标识。
当 Sequencer 播放器初始化时,它会读取一次 InstanceData。如果你在 Play 之后才设置,或者没有开启“允许覆盖”的开关,设置就不会被应用。
以下是解决此问题的核心步骤和代码实现:
- 核心原因:必须开启 bOverrideInstanceData
动态创建的 LevelSequenceActor 默认不会开启“覆盖实例数据”的开关。如果没有这个开关,即使你赋值了 TransformOriginActor,系统依然会忽略它并使用世界原点。
正确的蓝图 (Blueprint) 实现流程
在蓝图中,你需要确保在播放之前完成以下操作:Spawn Actor from Class: 选择 LevelSequenceActor。
Set Sequence: 指定你的 Level Sequence 资源。
Set bOverrideInstanceData: 将此布尔值设为 True。
Set DefaultInstanceData:
- 从 LevelSequenceActor 获取 DefaultInstanceData。
- 设置其中的 TransformOriginActor 成员。
Create Level Sequence Player: 使用该 Actor 作为 Init Settings 的一部分。
Play: 开始播放。
正确的 C++ 实现逻辑
在 C++ 中,最稳妥的方法是使用“延迟生成(Deferred Spawn)”,在 Actor 初始化完成前注入数据:
// 1. 延迟生成 LevelSequenceActor
ALevelSequenceActor* SequenceActor = GetWorld()->SpawnActorDeferred<ALevelSequenceActor>(
ALevelSequenceActor::StaticClass(),
FTransform::Identity
);
if (SequenceActor)
{
// 2. 指定序列资源
SequenceActor->SetSequence(MyLevelSequenceAsset);
// 3. 【关键】开启覆盖开关
SequenceActor->bOverrideInstanceData = true;
// 4. 【关键】设置原点数据
// 注意:DefaultInstanceData 是一个指向 FLevelSequenceInstanceData 的指针
if (SequenceActor->DefaultInstanceData)
{
SequenceActor->DefaultInstanceData->TransformOriginActor = TargetActor;
}
// 5. 完成生成
SequenceActor->FinishSpawning(FTransform::Identity);
// 6. 此时再 Play 就会立即生效
SequenceActor->SequencePlayer->Play();
}
- 为什么 Set Transform Origin 节点有时候无效?
如果你直接调用 LevelSequencePlayer 上的 SetTransformOrigin 节点:
时机问题:如果 Sequence 已经开始播放并更新了第一帧(Evaluate),初始位移可能已经根据旧的原点计算完成了。
生命周期问题:LevelSequencePlayer 只是逻辑执行器,位移补偿逻辑通常存储在 IMovieSceneTransformOrigin 接口中。如果底层 Actor 的覆写标志位没开,Player 往往无法强行更改已经在运行的 Track 偏移。
- 调试清单
检查是否已播放:确保设置逻辑在 Play 节点的前面。
检查 Root 轨道:确保你的序列中需要位移的对象是相对于场景根节点的,而不是绝对坐标。
消除 (Eliminate) 干扰:如果你的 Actor 身上有其他的坐标控制逻辑(比如物理模拟或附加到了其他 Actor),可能会与 Transform Origin 产生冲突。
刷新机制:如果必须在播放中更改,尝试先 Pause(),设置 TransformOrigin,然后调用 JumpToSeconds 或 JumpToFrame 强行让 Sequencer 重新计算(Re-evaluate)当前帧的偏移。
通过在 Spawn 阶段显式开启 bOverrideInstanceData 并填充 DefaultInstanceData,可以解决 90% 以上动态创建无效的问题。