做动作整合时被问得最多的问题之一,就是“我怎么只取这段动画里的某一段来用?”尤其在UE5.5里,动画资产来源五花八门:有从3ds Max导出的整段位移动画,有动捕直接录的长镜头,有从商店买来的“一体化”动作文件,里面既有走路又有跑步还有跳跃。直接拖进动画蓝图播放,要么从头播到尾,要么长度对不上,要么循环点不对。这篇就专门聊聊,怎样在UE5.5里把一段动画“切一刀”或者“框一段”出来使用,包括最基础的运行时区间控制、基于Montage的Section方案、以及在资产层面裁剪的具体操作。
这个话题适合所有在UE里做角色动画的人:不管是刚接触动画蓝图的新手,还是已经做了几年动画整合的TA、技术美术,甚至是负责虚拟制片里镜头动画的同事。我会尽量把每一步都拆开讲清楚,标注哪些做法容易被坑,哪些做法在项目实际落地时更稳妥。内容基于UE5.5正式版,但大部分技巧在UE5.0到5.6之间是通用的。
1. 要“选取一段”的几种真实场景与设计思路
1.1 需求到底从哪里来
先说一个最常见的场景:美术同事给你一条长达40秒的“角色待机+走路+跑步+转身”整段连续动画,是从引擎商城里买的,或者是从动捕设备里直接导出的“长镜头”。但你的游戏里需要的是一个3秒的待机循环,和一组独立的走跑循环。如果直接把整条动画丢进动画蓝图,播放效率极低,而且切循环时肯定有肉眼可见的“卡点”。这时候本质上就是两个选择:要么在引擎里把这段动画的某个区间“选”出来单独播放,要么把它裁剪成独立的新动画资产。
另一种场景和连招有关。很多动作游戏里的攻击动画是一整段连续的挥砍动作,但策划希望把它拆成“起手”“命中伤害判定”“收招”三个逻辑阶段。UE里最舒服的解法是把它放进Montage,用Section划分区间,然后在蓝图里只播放特定Section。这比复制三段动画再修三个文件要科学得多——因为资源只有一份,改动作时在源文件里改一次,所有Section同步生效。
还有一类偏引擎底层的使用方式:在动画蓝图里用Play Animation节点,老版本里只有StartPosition参数,没有EndTime。你常常会看到有一些人硬在蓝图里写计时器,播到某时刻再切换到别的状态,这种做法不推荐。后面的内容里我会给出更可控的方法。
1.2 分层思考:资产裁剪、运行时控制、逻辑分段
面对“选取一段”这个需求,先不要急着动手,先想清楚你是在哪个层面做这件事。这直接决定了你后续维护成本的高低。
- 资产裁剪:在Animation Sequence编辑器里用Scrub或Trim工具,把指定范围之外的帧删掉,生成一个新动画资源。适合不需要再编辑原始长镜头、确定区间不会反复改、以及移动端包体有烘焙压力的情况。
- 运行时控制:在动画蓝图或Gameplay逻辑里,给播放节点传入“起始位置”。相当于播放时从动画的某个时间点跳到另一个时间点。没有真正改变资源,灵活,但会导致“播放完指定区间后的行为”需要自己控制。
- 逻辑分段:用AnimMontage的Section机制,在动画内部定义多个命名区间,运行时通过Montage_PlayWithBlend指定Section,或者通过Montage_SetNextSection切换。这是最接近“选取一段”语义的方式,而且能和事件通知、Root Motion配合得很好。
我在实际项目里通常的排序是:优先用Montage Section,因为它兼顾灵活和性能;如果只是临时看效果,用Play Animation的StartPosition参数;只有在包体大小极敏感、或者这段动画永远不会再动的情况下,才去裁剪资产。
1.3 为什么不要“硬切”
很多人一上来就想着“我把动画资产的起始帧改成我要的位置,播放就从这里开始”。这个思路在UE里可行,但在流程上风险很高。因为你在动画资产里改的起始点,会直接污染所有引用这个动画的地方——其他动画蓝图、蒙太奇、Sequencer里引用到这条动画的地方都会跟着变。你为了一个需求,把别的需求全弄坏了。
更聪明的思路是“不改数据,改DOP”——也就是通过播放器和容器机制来限定区间。UE的动画系统本质上支持在多个层面上“框选区间”,只要理解了播放时间轴和“Section”的关系,就能做到既不破坏原始数据,又达到和裁剪一样的效果。
2. 核心机制解析:时间轴、Section、PlayRange到底怎么算
2.1 动画的时间轴与帧率换算
在UE5.5里,每一条Animation Sequence都有固定的帧速率(Display Rate)和关键帧数据。你打开动画资产时,底部时间轴上每个格子的宽度由Frame Rate决定,显示的数值单位是帧,也可以切到秒(Seconds)显示。
当我们讨论“选取一段”时,不可避免地要把帧范围换算成时间。计算公式很简单:时间(秒)= 帧数 / 帧速率。假设动画是30fps,你要选取从第12帧到第60帧,那么对应的时间范围就是 0.4秒到2.0秒。如果动画是按60fps烘焙的,一样换算。这里必须注意:UE动画在导入时会有一个“采样率”的概念,如果你在导入设置里勾选了Auto Reimport或允许引擎重采样,那么帧率变了,原本的帧位置对应的实际动作也会变化。要避免这种问题,导出的帧率和引擎里Asset Details面板的FrameRate尽量保持一致。
很多“播放段不对劲”的问题都是帧率换算错误导致的。尤其是从3ds Max或者Maya导出时,有的项目习惯用24fps做动画,导进UE后没有把Import Frame Rate改成24,引擎默认按30fps解释,播放速度就快了25%,你选中的帧段在时间上的真实位置是不可信的。
2.2 PlayRate、StartPosition与播放范围的关系
在动画蓝图中,最常见的播放节点是“Play Animation”或“Play Montage”。前者是直接在AnimGraph里对某个AnimSequence播放,后者是写在动画蓝图里控制Montage实例。
Play Animation节点有几个关键属性:
- Play Rate:播放速度倍率,1.0为原始速度,2.0为双倍速。
- Start Position:播放开始的起点,单位是秒,也可以是“基于动画长度比例”的模式切换。
- Should Loop:是否循环。
- Playback Range:严格来说,Play Animation节点自身没有暴露开始/结束时间范围,但你可以用节点的“Loop”配合后续逻辑来模拟。如果想精确圈定结束点,得用时间轴状态机或者Montage。
这也就是说,单纯用AnimGraph里的Play Animation来“选取一段”是个不完整的方案。它只能帮你从任意位置开始。那结束怎么控制?我看到很多人用了一个笨方法:在动画蓝图里创建一个TimeRemap节点,把AnimSequence的采样时间映射到某个区间。这个方法不是不行,但调试时很痛苦,曲线折来折去,没有可视化界面,不推荐给普通项目。
2.3 Section是UE给的“原生选区”机制
在Animation Sequence编辑器的左上角,有一块叫做Section的面板,默认只有一条空白的区间。你可以通过右键点击时间轴拖动选择一段范围,然后点击“Create Section”来建立一个带名称的区间。
Section的本质就是给动画时间轴划了“段落”,而且这些段落可以在动画蓝图、Montage、以及蓝图函数中被引用。这就引出了UE5.5里最核心的“选取一段使用”方式:把动画丢进Montage,在Montage里用Section来标识区间,然后通过Montage_PlayWithBlend并传入SectionName来播放你选中的那一段。
Montage的Section和AnimSequence的Section并不是一回事,但可以继承。当你把一个AnimSequence添加到Montage中时,Animation Sequence里已有的Section会自动变成Montage中该动画片段下的Section。你也可以在Montage的Section面板里重新定义区间。
2.4 动画通知与选取区间的配合
选取一段动画之后,往往还需要在这段区间内触发“事件”或“特效”,比如攻击动作砍到敌人时播放打击特效。UE里可以用Notifies解决。如果在Animation Sequence里创建的是Notify,那么它依附于该动画的时间点;如果你在Montage里创建的是Montage Notify,它则依附于Montage的时间轴。
这里最隐蔽的坑是:当你把动画片段(AnimSequence)拖进Montage,并且设置了Section的开始/结束位置,动画本身自带的Notifies依然会按原始帧触发,不会因为“选取了一段”而自动偏移。举例来说,原始动画第20帧有一个“脚步落地”通知,你选取了第30到第60帧作为一个Section,第20帧的通知依然会在Section播放到那段原始时间时触发——但由于Section从30帧开始播放,第20帧的通知可能永远不会在Section的播放过程中出现。如果你希望它跟着选取区间走,需要在Montage里重新添加Notifies,或者删除原动画中多余的Notify。
很多动画师在“选取一段”后总是说“为什么脚步声没了”,原因就在这里。你在资产层面裁切时,通知是会被裁剪掉的;但你在Montage Section里做逻辑分段时,通知依然挂在原始动画的时间轴上,不会自动跟随。理解了这条,排查问题就快了。
3. 实操:三条路径从零到一完整演示
3.1 路径A:动画蓝图中的StartPosition快速播放
这个最简单,适合临时预览。新建或打开一个AnimBlueprint,在Event Graph中获取AnimInstance,然后调用PlayAnimation,设置StartPosition。
操作步骤如下:
- 在Content Browser中选中你希望截取片段的AnimSequence。
- 打开关联的AnimBlueprint,在AnimGraph中使用一个
Play Animation节点,把AnimSequence连接到该节点。 - Select该节点,在Details面板中把
Start Position设置为你要开始的时间,单位是秒。比如要从1.5秒处开始,就填1.5。 - 默认情况下播放会在动画结尾停下。如果希望只播放2秒,需要自己控制“停止”:可以用一个Timer或者Timeline,在0.5秒后切换到其他状态,比如切换到Idle。
这套方法的优点是完全无需改动资产,跑起来就能看到区间效果。缺点是结束时间全靠外部计时,如果要精确到帧,容易误差。我个人认为它比较适合做“快速验证这个区间是否好看”,而不是作为正式玩法逻辑。
3.2 路径B:AnimMontage + Section(正式玩法推荐)
这才是真正适合项目落地的方案。先说前置条件:
- 准备一条完整的AnimSequence。
- 在Animation Sequence编辑器中先创建好Section,或者直接在Montage里创建。
完整步骤:
- 在Content Browser中右键 -> 动画 -> 动画蒙太奇(AnimMontage),选择基于目标骨骼和AnimSequence创建。最好先选中源动画,然后右键 -> Create -> AnimMontage,这样蒙太奇会自动包含该动画。
- 打开Montage,你会看到上方的叠加层有AnimSequence所在的轨道和底部时间轴。
- 在时间轴标尺上拖动选择一个播放范围(蓝/白高亮选区),点击顶部工具栏的
Create Section按钮,在弹出的命名框里填一个有意义的名称,比如Attack_Start、Attack_Impact、Attack_Recover。 - 为每个区间创建好Section后,在蓝图或动画蓝图逻辑里调用
Montage_PlayWithBlend。第一个参数是Montage资产,第二个参数是BlendIn时间,第三个参数是Montage播放速率,第四个参数(In Section Name)填你要播放的Section的名称。 - 如果需要连招切换,可以调用
Montage_SetNextSection,参数里传当前Section名、下一个Section名、以及Montage实例。这样也在动作播放到某个Section结束时自动跳转。
为什么这个方案最强?因为Section本质上是一个“起始点”加上“播放长度”的组合。Montage会自动从Section起始帧开始播放,到Section结束帧后,你可以配置EndSection时的行为(比如停止、跳转到下一个Section)。再加上Montage本身支持Slot叠加、RootMotion设置、Montage事件,你就可以把“只播放攻击动画的挥砍阶段”这一业务目标完整映射到引擎机制上。
还有一个小技巧:如果你不想在Animation Sequence编辑器里预先创建Section,也可以在Montage里直接用鼠标选择时间范围后点Add Section。但强烈建议在源动画里就划分好,因为这样多个Montage共用同一个动画时会复用相同的区间语义。比方说你有两个蒙太奇都引用了同一个攻击动画,它们可以直接通过SectionName调用同一个区间,修改源动画时两个蒙太奇都同步更新。
3.3 路径C:资产级裁剪生成独立动画
如果你确实需要把“那一段”变成一个新的动画文件,用Trim命令。步骤:
- 双击打开AnimSequence。
- 在时间轴下方有一个
缩略图区域(Scrub Area),你可以通过拖动左右两个边界手柄来框选想要保留的范围。UE里管这个叫Trim(修剪)。 - 框选好后,在工具栏选择
Trim按钮,或者右键选择修剪,引擎会保留选区内的动画,删除选区外的所有帧。 - 如果只想查看选取段而不破坏原资产,可以用
Scrub或者“选区预览”功能。但Trim是真实修改,执行前需要小心。
注意:Trim会直接改变当前动画资产。常见的做法是先把源动画复制一份(右键 -> Duplicate),再对副本执行Trim。否则你原本的完整动作就没了,后面想改区间都没办法。
在UE5.5的资产细节中,还可以手动编辑Playback Range或者Sequence Length。不过这个方式不建议普通用户使用,容易造成关键帧时间错乱。最好还是用可视化的裁剪。
3.4 路径D(进阶):Level Sequence里框选播放范围
如果是过场动画、广告动画生成、甚至是wpf/ppt这类非引擎工具,大家更关心的可能是“序列器”里的方式。在UE5.5的Sequencer中,你可以把任意动画数据作为SubSequence或者动画资产拖入轨道。
- 选中该轨道上的动画片段,在属性面板中设置
Start Frame和End Frame即可只播放这一段。 - 也可以直接在Sequence时间轴上对剪辑片段进行
Trim操作(右键片段 -> Trim -> 开始裁剪/结束裁剪)。 - 更精细的控制是使用
Level Sequence的“Play Range”:在Outliner中选中Sequence Actor,设置Start Frame和End Frame,播放序列时只在这两帧之间往返。
这个场景多用于广告动画生成等重剪辑的场景,比如拿一段角色表演动画,在Sequencer里把它截取到某个镜头内,配合摄像机运镜,比在动画资产层面裁切灵活很多。
4. 常见问题与排查技巧实录
4.1 为什么StartPosition没生效
在动画蓝图里设置了Start Position,但运行时发现动画还是从头播放。最常见的原因是你在AnimGraph中连接了多个数据源,而最终输出的是别的节点。StartPosition只作用于Play Animation节点及其下游的数据流,如果你后边还有Layered Blend或者Slot节点,它们可能会忽略StartPosition。
排查方法:先断开所有其他Blend输入,单独看Play Animation的输出。确认节点参数确实应用了当前实例而不是共享的动画蓝图默认值。
4.2 播放到Section结束时出现跳帧
Montage Section播放结束后,如果配置的Next Section不存在或者当前Section的LoopState不对,就会直接跳到Montage末尾。你用Montage_PlayWithBlend直接播放指定Section时,如果下一个Section没有配置成“无”,它可能默认跳回第一个Section(或者Montage的DefaultSection)。
所以我在创建Section时,通常会把流程想清楚:要么每个Section的NextSection都指向一个名为None的占位节点(即播完就End),要么明确指向下一个连招Section。不要留空,留空是很多“跳帧”问题的根源。
4.3 循环一段动画时,循环点前后动作不连续
如果你想做的其实是“选取一段待机循环”,而不是“选取一段一次性动作”。用Montage Section就不太合适了——Montage是按一次性片段设计的,Section循环需要额外配置。更合适的做法是拿这条动画去驱动一个Loop播放节点,并且把StartPosition设为某帧来对齐起始动作。
但这种方法不能保证结束点恰好接上起始点。如果需要完美循环,建议你回到源动画编辑器,框选这个区间后使用Create Section,然后在动画资产的Loop相关设置里把Loop Mode改为对应模式(比如In Place Loop或Cycle)。或者直接在Animation Sequence本身设置Interpolation和Loop参数,让它按段循环。
4.4 根骨骼运动(Root Motion)为何对不准
当你“选取一段”而这一段的起始点不在“脚着地”的帧上,或者没有与RootMotion的位移轨迹对齐,就会出现滑步。这个问题在Montage里尤其明显,因为Montage默认会根据Section起点来计算根骨骼偏移。检查方法:在MontageAsset的细节面板 ->根骨骼运动->根骨骼,确保RootMotion模式设置正确,通常为MatchingRelative或者FromAnimation。如果你希望Section的起点与当前角色位置对齐,注意看是否启用了Start From Anim和Extract Root Motion。
另一个坑:裁剪AnimSequence时,RootMotion轨迹的起始位置会被归零化,但如果你选取的区间内包含了大量位移,归零后角色会在起始帧瞬间被拉回原点。要么保留原始动画并处理好RootMotion模式,要么在裁剪后手动修正RootMotion的起始偏移。
4.5 通知不触发/触发偏移
上面说过,Section不影响原始Notify的位置。还有一个频繁出现的问题:在Montage里添加了Montage通知,但在Section播放时这个通知就是不出。原因是Montage的通知属于“全局”时间轨,如果Section的起始帧超过了通知所在帧,而Section又从新起点开始播放,通知不会出现在播放窗口内。解决办法是:给通知设置触发时间为相对时间,或者直接把通知加到Montage对应的Section内部——UE5.5中你可以右键点击Section内部的轨道区域,创建归属于该Section的Notify,它只在播放该Section时触发。
4.6 动画显示不全 / 裁掉了一部分
有一些奇怪的现象:新版本的某个动画只播放了后半部分,或者只播放了前半部分。多半是这套动画本身带有Playback Range的范围限制。在Animation Sequence编辑器里,留意时间轴顶部是否有两把锁一样的十字标,它表示当前播放范围,可能被以前的操作误调了。重置方法:在资产细节面板找到Playback Range,把Start Frame和End Frame设为全片范围。
或者在导入设置里勾选了裁剪动画,导致引擎根据根骨骼的位移或曲线自动裁剪了首尾空白帧。这个在UE5.5的Import Settings -> Animation里有Remove Root Motion和Trim Diagnostics等参数。如果你导入后动画突然变短了,检查这一项。
4.7 网络同步下客户端的Section播放不一致
多人游戏里,服务端播放Montage并同步到客户端,但客户端经常出现“Section没选中”的情况。Montage复制时有专门的复制选项,需要勾选复制和在属性复制时复制完整动画等。而在Section切换上,不能用客户端自己调用Montage_SetNextSection,要由服务端RPC命令来调用,否则两个端的Section不同步。
我开始做项目时也在这里吃过亏:本地测试正常,两个人联机时A看到的连招是A动作,B看到的是B动作。后来统一在服务端执行Montage_SetNextSection,客户端只负责播放服务端指定的Section名称,问题解决。
5. 我的实操习惯与一些额外建议
做完这些,分享几个我个人在项目中固定的操作习惯。
- 源动画永远保留一份,不要轻易Trim原始资产。需要裁切时,Completely Duplicate一份再处理。
- 在Animation Sequence编辑器里,给常用区间都建立有名Section,统一用命名规范比如
Atk_Start、Atk_Loop、Atk_End,这样动画蓝图里读起来一目了然。 - 在Montage里做连招时,每个Section的
NextSection一定要显式设置。不能懒。 - 遇到“选取一段播放但首尾姿势闪跳”的情况,优先检查BlendIn时间和Root Motion,不是去调Section。
从维护角度看,我这几年用的最多的还是“AnimMontage + Section”。它把“选取”这件事从代码层的计时器逻辑提升到了美术资源层的可视化区间,动画师自己就能理解和修改。而当你需要临时抽出某一小段来做宣传片、特效预览、广告动画生成,直接用Sequencer的PlayRange裁剪就好,不需要动游戏内资产。
最后再补充一个小技巧:如果你用的是刚导入的长动画,且不确定它的帧率,先看资产详情面板里的帧率和播放长度。很多“选取位置不对”的问题就是帧率理解错了,导致你以为填的是1秒,实际播放到另一段。先确认基础数值,再谈选取区间,这是所有动画整合工作的第一句咒语。