关于 ue-sequencer-cinematics
面向 Unreal Engine 5.8 开发者的 Sequencer 与电影化工作流技能,提供经 5.8 头文件核对的运行时和编辑器 API 指引,涵盖播放、绑定、事件轨道及渲染。
主要功能
- 01Sequencer 模块依赖指引
- 02运行时播放与绑定
- 03事件轨道调用规则
- 04MovieScene 数据模型说明
- 05电影摄影机与渲染指引
适用场景
- 01实现游戏内过场动画播放
- 02将序列绑定到运行时 Actor
- 03从时间轴事件调用 C++
- 04配置序列数据与离线渲染
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-sequencer-cinematics安装后在 Claude Code 中输入/ue-sequencer-cinematics确认已加载。
附带文件references/sequencer-patterns.md
详细介绍
UE Sequencer 与电影制作
目标引擎:UE 5.8。以下 API 已根据 5.8 头文件验证;旧版本形式列在“已弃用 — 请勿使用”下。
Sequencer 涉及三个运行时模块和一个插件。MovieScene 存放数据模型和播放器基类,MovieSceneTracks 存放具体的轨道和区段类型,LevelSequence 存放资源、Actor、播放器和导演,CinematicCamera 存放电影摄影机和摄影机装置。离线渲染由 Movie Render Queue 插件提供(运行时使用 MovieRenderPipelineCore,编辑器队列 UI 使用 MovieRenderPipelineEditor);该插件默认处于禁用状态,必须在 .uproject 中启用。
上下文
如果 .agents/ue-project-context.md 存在,请阅读它(模块名称、约定、已启用的插件、GAS/网络设置)。如果文件不存在,也不要因此停下。
根据请求和代码库识别相关领域。只有在两种合理解读会导致不同代码时才提问。
| 请求涉及…… | 前往 |
|---|---|
| 要在 Build.cs 中添加哪些模块 | Build.cs 模块 |
| C++ 在运行时与仅编辑器环境下分别能做什么 | 运行时与编辑器 |
| 启动、停止、跳转或循环播放序列 | 播放 Level Sequence |
| 将序列轨道指向游戏中的 Actor | 在运行时绑定 Actor |
| 在时间轴的某个键上调用 C++ | Sequencer 事件轨道 |
| 轨道、区段、子序列、帧计算 | MovieScene 数据模型 |
| 电影摄影机设置、焦点、轨道和吊臂 | 电影摄影机与摄影机装置 |
| 将帧或视频渲染到磁盘 | Movie Render Graph |
| 完整的过场动画、多人游戏和摄影机装置示例 | Sequencer 运行时模式 |
Build.cs 模块
PublicDependencyModuleNames.AddRange(new string[]
{
"LevelSequence", // ULevelSequence, ALevelSequenceActor, ULevelSequencePlayer, ULevelSequenceDirector
"MovieScene", // UMovieScene, UMovieSceneSequencePlayer, FMovieSceneObjectBindingID
"MovieSceneTracks", // UMovieSceneEventTrack, UMovieSceneCameraCutTrack, property tracks
"CinematicCamera", // ACineCameraActor, UCineCameraComponent, ACameraRig_Rail, ACameraRig_Crane
});
// Offline rendering only. Requires the MovieRenderPipeline plugin enabled in the .uproject.
PrivateDependencyModuleNames.Add("MovieRenderPipelineCore");
运行时与编辑器
创建序列属于编辑器操作。正式发布的游戏代码负责播放和重新绑定序列,而不是创建序列。
| 任务 | API | 可用性 |
|---|---|---|
| 播放、停止、跳转、设置播放速率 | UMovieSceneSequencePlayer | 运行时 |
| 覆盖绑定所解析到的 Actor | ALevelSequenceActor::SetBinding* | 运行时 |
| 读取轨道、绑定、帧速率 | UMovieScene getter、UMovieSceneSequence::GetMovieScene | 运行时 |
| 从时间轴调用 C++ | ULevelSequenceDirector 子类 | 运行时 |
| 将渲染加入队列并运行 | UMoviePipelineQueueEngineSubsystem(UEngineSubsystem) | 运行时 |
| 向序列添加 Actor、摄影机和可生成对象 | ULevelSequenceEditorSubsystem(UEditorSubsystem) | 仅编辑器 |
| 以脚本方式创建轨道/区段并设置键 | UMovieSceneSequenceExtensions(Beta SequencerScripting 插件的运行时模块) | 编辑器脚本 — 会修改资源 |
| 注册自定义轨道编辑器 | ISequencerModule::RegisterTrackEditor | 仅编辑器 |
| 控制 Movie Render Queue 窗口 | UMoviePipelineQueueSubsystem(UEditorSubsystem) | 仅编辑器 |
UMovieScene::AddTrack 和 UMovieSceneSubTrack::AddSequence 会编译进运行时构建,但它们会修改序列资源。只能从编辑器工具或命令程序中调用它们;不得在已发布的游戏中编辑经过烘焙的 ULevelSequence。
播放 Level Sequence
从已放置的 ALevelSequenceActor 播放
#include "LevelSequenceActor.h"
// LevelSequenceActor.h:153 — UFUNCTION(BlueprintGetter) ULevelSequencePlayer* GetSequencePlayer() const;
if (ULevelSequencePlayer* Player = SeqActor->GetSequencePlayer())
{
Player->Play();
}
ALevelSequenceActor 的实用成员:PlaybackSettings、LevelSequenceAsset、BindingOverrides、DefaultInstanceData、bOverrideInstanceData、bReplicatePlayback、GetSequence()、SetSequence()、SetReplicatePlayback()。自动播放由 PlaybackSettings.bAutoPlay 控制;Actor 自身已不再有 bAutoPlay 字段。AReplicatedLevelSequenceActor 是始终与网络相关的子类。
在运行时生成播放器
#include "LevelSequencePlayer.h"
#include "MovieSceneSequencePlaybackSettings.h"
// LevelSequencePlayer.h:106
// static ULevelSequencePlayer* CreateLevelSequencePlayer(
// UObject* WorldContextObject, ULevelSequence* LevelSequence,
// FMovieSceneSequencePlaybackSettings Settings, ALevelSequenceActor*& OutActor);
FMovieSceneSequencePlaybackSettings Settings;
Settings.bAutoPlay = false;
Settings.PlayRate = 1.0f;
Settings.StartTime = 0.0f; // seconds into the playback range
Settings.LoopCount.Value = 0; // 0 = once, -1 = infinite, N = N extra loops
Settings.bDisableMovementInput = true;
Settings.bDisableLookAtInput = true;
Settings.bHidePlayer = false;
Settings.bHideHud = true;
Settings.bDisableCameraCuts = false;
Settings.bPauseAtEnd = false;
Settings.bDynamicWeighting = false; // set true (or enable it on the asset) before using SetWeight() — MovieSceneSequencePlayer.h:278
Settings.FinishCompletionStateOverride = EMovieSceneCompletionModeOverride::ForceRestoreState;
ALevelSequenceActor* OutActor = nullptr;
ULevelSequencePlayer* Player = ULevelSequencePlayer::CreateLevelSequencePlayer(
this, CutsceneAsset, Settings, OutActor);
ActiveSequenceActor = OutActor; // UPROPERTY member — otherwise both are collected
ActivePlayer = Player; // UPROPERTY member
// Remaining fields: bRandomStartTime, TickInterval, bInheritTickIntervalFromOwner
播放控制
Player->Play();
Player->PlayReverse();
Player->PlayLooping(-1); // -1 = infinite
Player->ChangePlaybackDirection();
Player->Pause();
Player->Scrub();
Player->Stop(); // resets the cursor and fires OnStop
Player->StopAtCurrentTime();
Player->GoToEndAndStop();
Player->SetPlayRate(0.5f);
Player->SetFrameRange(0, 60); // (StartFrame, Duration) in display-rate frames
Player->SetTimeRange(0.0f, 2.5f); // (StartTime, Duration) in seconds
// Seek without firing the events in between
Player->SetPlaybackPosition(
FMovieSceneSequencePlaybackParams(FFrameTime(120), EUpdatePositionMethod::Jump));
// Advance to a frame, firing every event along the way
Player->PlayTo(
FMovieSceneSequencePlaybackParams(FFrameTime(240), EUpdatePositionMethod::Play),
FMovieSceneSequencePlayToParams());
// Seconds instead of frames: FMovieSceneSequencePlaybackParams(2.5f, EUpdatePositionMethod::Jump)
const bool bPlaying = Player->IsPlaying();
const FQualifiedFrameTime Now = Player->GetCurrentTime();
const FQualifiedFrameTime Dur = Player->GetDuration();
const FFrameRate Rate = Player->GetFrameRate();
EUpdatePositionMethod 可以是 Play、Jump 或 Scrub。FMovieSceneSequencePlaybackParams 提供接受 FFrameTime、float 秒数、标记帧名称 FString 或 FTimecode 的构造函数。
委托
// UPROPERTY(BlueprintAssignable) FOnMovieSceneSequencePlayerEvent — dynamic, no parameters
Player->OnPlay.AddDynamic(this, &AMyCutsceneManager::HandleSequencePlay);
Player->OnStop.AddDynamic(this, &AMyCutsceneManager::HandleSequenceStop);
Player->OnFinished.AddDynamic(this, &AMyCutsceneManager::HandleSequenceFinished);
Player->OnPause.AddDynamic(this, &AMyCutsceneManager::HandleSequencePause);
Player->OnNativeFinished.BindUObject(this, &AMyCutsceneManager::HandleNativeFinished); // native
// LevelSequencePlayer.h:27 — DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
// FOnLevelSequencePlayerCameraCutEvent, UCameraComponent*, CameraComponent)
Player->OnCameraCut.AddDynamic(this, &AMyCutsceneManager::HandleCameraCut);
只有播放自然结束时才会触发 OnFinished(自然结束也会触发 OnStop);显式调用 Stop() 时只会触发 OnStop。请在调用 Play() 之前绑定。
在运行时绑定 Actor
可占有对象会解析为关卡中已存在的 Actor。可生成对象由序列本身创建和销毁。可占有对象的生命周期超出序列;可生成对象则不会。运行时覆盖适用于可占有对象。
在 Sequencer 编辑器中为对象绑定添加标签(右键单击绑定,然后选择 Tags),再从 C++ 按标签覆盖——重新绑定后标签仍会保留,但 GUID 不会。
#include "LevelSequenceActor.h"
#include "MovieSceneObjectBindingID.h"
// LevelSequenceActor.h:178-253
SeqActor->SetBindingByTag(FName("Hero"), TArray<AActor*>{ HeroActor },
/*bAllowBindingsFromAsset=*/ false);
SeqActor->AddBindingByTag(FName("Crowd"), ExtraActor, /*bAllowBindingsFromAsset=*/ true);
SeqActor->RemoveBindingByTag(FName("Crowd"), ExtraActor);
// GUID form — expose the ID so a designer can pick the binding in the details panel:
// UPROPERTY(EditAnywhere, Category = "Cinematics") FMovieSceneObjectBindingID HeroBindingID;
SeqActor->SetBinding(HeroBindingID, TArray<AActor*>{ HeroActor }, false);
SeqActor->AddBinding(HeroBindingID, HeroActor, false);
SeqActor->RemoveBinding(HeroBindingID, HeroActor);
SeqActor->ResetBinding(HeroBindingID); // back to whatever the asset says
SeqActor->ResetBindings(); // clear every override
const FMovieSceneObjectBindingID Found = SeqActor->FindNamedBinding(FName("Hero"));
const TArray<FMovieSceneObjectBindingID>& All = SeqActor->FindNamedBindings(FName("Crowd"));
// What is actually bound right now
TArray<UObject*> Bound = Player->GetBoundObjects(HeroBindingID);
FMovieSceneObjectBindingID 将其 guid 和序列 id 设为私有。使用 GetGuid()、GetRelativeSequenceID() 和 IsFixedBinding() 读取;使用 ResolveToFixed() 将 ID 移动到子序列层级中,然后对生成的 UE::MovieScene::FFixedObjectBindingID 调用 ConvertToRelative()(ConvertToRelative 不是 FMovieSceneObjectBindingID 的成员,MovieSceneObjectBindingID.h:113-160,341)。切勿直接赋值给这些字段。
重新定位整个序列
ALevelSequenceActor 实现了 IMovieScenePlaybackClient::GetInstanceData。设置 bOverrideInstanceData 并提供一个 UDefaultLevelSequenceInstanceData,即可偏移每个绝对变换片段,让同一个已创作的过场动画可以在世界中的任意位置播放。
#include "DefaultLevelSequenceInstanceData.h"
UDefaultLevelSequenceInstanceData* Data =
NewObject<UDefaultLevelSequenceInstanceData>(SeqActor);
Data->TransformOriginActor = StageMarkerActor; // or leave null and set TransformOrigin
SeqActor->DefaultInstanceData = Data;
SeqActor->bOverrideInstanceData = true;
Sequencer 事件轨道
事件关键帧不会调用不相关的全局函数。FMovieSceneEvent 存储已编译的 UFunction 指针,求值系统会在序列的导演实例上调用它——该对象是 ULevelSequence::DirectorClass 中的类的实例,而该类继承自 ULevelSequenceDirector。因此,UFUNCTION 必须是 ULevelSequenceDirector 子类或其 Director Blueprint 的成员。
引擎强制执行以下规则:
MovieSceneEvent.h:70— 端点不接受任何参数,或只接受一个按值传递的对象/接口参数,并且不返回任何内容。- 当事件轨道位于对象绑定下时,被绑定对象会作为该唯一参数传入。
- 在根轨道上,无参数端点会在导演实例上运行一次;带对象参数的端点会针对每个全局事件上下文运行一次(
MovieSceneEventSystems.cpp:206-213)。ULevelSequencePlayer::GetEventContexts返回持久关卡的ALevelScriptActor,以及每个流送关卡各自的一个实例——而不是UWorld。 - 在非游戏世界(Sequencer 预览)中,除非
UFUNCTION带有CallInEditor,否则会跳过该事件。
// MyCinematicDirector.h
#pragma once
#include "LevelSequenceDirector.h"
#include "MovieSceneObjectBindingID.h"
#include "MyCinematicDirector.generated.h"
class AActor;
UCLASS(Blueprintable)
class MYGAME_API UMyCinematicDirector : public ULevelSequenceDirector
{
GENERATED_BODY()
public:
/** Event endpoint with no parameters. */
UFUNCTION(BlueprintCallable, CallInEditor, Category = "Cinematics")
void OnExplosionCue();
/** Event endpoint on an object-binding track: receives the bound actor. */
UFUNCTION(BlueprintCallable, CallInEditor, Category = "Cinematics")
void OnActorCue(AActor* BoundActor);
/** Assign in the Director Blueprint's class defaults using the Get Sequence Binding node. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cinematics")
FMovieSceneObjectBindingID HeroBinding;
};
// MyCinematicDirector.cpp
#include "MyCinematicDirector.h"
#include "LevelSequencePlayer.h"
#include "GameFramework/Actor.h"
void UMyCinematicDirector::OnExplosionCue()
{
// GetBoundObjects and Player are both declared on ULevelSequenceDirector.
for (UObject* Object : GetBoundObjects(HeroBinding))
{
if (AActor* Hero = Cast<AActor>(Object))
{
Hero->SetActorHiddenInGame(true);
}
}
if (Player)
{
Player->SetPlayRate(0.25f);
}
}
void UMyCinematicDirector::OnActorCue(AActor* BoundActor)
{
if (BoundActor)
{
BoundActor->SetActorTickEnabled(false);
}
}
要将其附加到序列:打开 Level Sequence,通过 Sequencer 工具栏打开其 Director Blueprint,然后将该 Blueprint 重设父类为 UMyCinematicDirector(Class Settings,Parent Class)。Sequencer 会将 Blueprint 编译到 ULevelSequence::DirectorClass 中;求值期间每个序列会创建一个导演实例,而 ULevelSequenceDirector::Player 指向所属的播放器。ULevelSequenceDirector 还提供 GetBoundObject、GetBoundActor、GetBoundActors、GetSequence、GetCurrentTime、GetRootSequenceTime 以及 BlueprintImplementableEvent OnCreated。
涉及的轨道类包括 UMovieSceneEventTrack(带有 bFireEventsWhenForwards)、用于一次性关键帧的 UMovieSceneEventTriggerSection,以及用于每次经过时都会触发关键帧的 UMovieSceneEventRepeaterSection。使用 EUpdatePositionMethod::Jump 跳转时会跳过中间的所有事件;如果必须触发这些事件,请使用 PlayTo。
MovieScene 数据模型
#include "MovieScene.h"
#include "MovieSceneSpawnable.h"
#include "MovieScenePossessable.h"
UMovieScene* MS = SeqActor->GetSequence()->GetMovieScene();
const FFrameRate DisplayRate = MS->GetDisplayRate();
const FFrameRate TickResolution = MS->GetTickResolution();
const TRange<FFrameNumber> Range = MS->GetPlaybackRange();
for (int32 Index = 0; Index < MS->GetPossessableCount(); ++Index)
{
const FMovieScenePossessable& Possessable = MS->GetPossessable(Index);
const FGuid Guid = Possessable.GetGuid(); // also GetName, GetPossessedObjectClass
}
for (int32 Index = 0; Index < MS->GetSpawnableCount(); ++Index)
{
const FMovieSceneSpawnable& Spawnable = MS->GetSpawnable(Index); // GetGuid, GetName
}
const TArray<UMovieSceneTrack*>& RootTracks = MS->GetTracks();
if (const FMovieSceneBinding* Binding = MS->FindBinding(SomeGuid))
{
for (UMovieSceneTrack* Track : Binding->GetTracks()) { /* Cast to a concrete type */ }
}
轨道类(MovieSceneTracks) | 动画对象 |
|---|---|
UMovieScene3DTransformTrack | Actor 和组件变换 |
UMovieSceneSkeletalAnimationTrack | 骨骼网格体动画 |
UMovieSceneCameraCutTrack | 视口使用的摄像机 |
UMovieSceneEventTrack | Director 函数调用 |
UMovieSceneAudioTrack | 声音资源 |
UMovieSceneFadeTrack | 屏幕淡入淡出 |
UMovieScenePropertyTrack | 属性动画的基类 |
UMovieScenePropertyTrack 的子类会驱动标记为 Interp 的命名 UPROPERTY:UMovieSceneFloatTrack 会生成 UMovieSceneFloatSection,后者存储一个 FMovieSceneFloatChannel;UMovieSceneBoolTrack 和 UMovieSceneColorTrack 也遵循相同的结构。UMovieSceneSubTrack 和 UMovieSceneSubSection 属于 MovieScene,而非 MovieSceneTracks。
#include "Tracks/MovieSceneSubTrack.h"
#include "Sections/MovieSceneSubSection.h"
UMovieSceneSubTrack* SubTrack = RootMovieScene->AddTrack<UMovieSceneSubTrack>();
const FFrameNumber Start = (2.0 * RootMovieScene->GetTickResolution()).FloorToFrame();
const int32 Duration = (5.0 * RootMovieScene->GetTickResolution()).FloorToFrame().Value;
UMovieSceneSubSection* SubSection = SubTrack->AddSequence(ChildSequence, Start, Duration);
SubSection->Parameters.TimeScale.Set(1.0); // FMovieSceneTimeWarpVariant — Set(), not assignment
SubSection->Parameters.bCanLoop = false;
SubSection->Parameters.StartFrameOffset = FFrameNumber(0);
子区段的偏移量和时长以刻度分辨率帧为单位,而非显示帧率帧。MovieSceneTimeHelpers.h 中的 UE::MovieScene::DiscreteSize、DiscreteInclusiveLower 和 DiscreteExclusiveUpper 可将 TRange<FFrameNumber> 转换为帧数。
电影摄像机和摄像机机架
本节介绍由序列驱动的摄像机。游戏摄像机、摄像机修改器、摄像机抖动和视图目标混合属于 ue-gameplay-cameras。
#include "CineCameraActor.h"
#include "CineCameraComponent.h"
#include "CineCameraSettings.h"
ACineCameraActor* Cam = GetWorld()->SpawnActor<ACineCameraActor>(SpawnLocation, SpawnRotation);
UCineCameraComponent* CineComp = Cam->GetCineCameraComponent();
FCameraFilmbackSettings Filmback; // SensorWidth / SensorHeight in mm
Filmback.SensorWidth = 36.0f;
Filmback.SensorHeight = 24.0f;
CineComp->SetFilmback(Filmback); // SensorAspectRatio is derived, not settable
FCameraLensSettings Lens; // mm and f-stops
Lens.MinFocalLength = 35.0f;
Lens.MaxFocalLength = 35.0f;
Lens.MinFStop = 1.4f;
Lens.MaxFStop = 16.0f;
Lens.MinimumFocusDistance = 30.0f;
Lens.DiaphragmBladeCount = 7;
CineComp->SetLensSettings(Lens);
FCameraFocusSettings Focus;
Focus.FocusMethod = ECameraFocusMethod::Manual; // DoNotOverride|Manual|Tracking|Disable
Focus.ManualFocusDistance = 500.0f; // cm
Focus.bSmoothFocusChanges = true;
Focus.FocusSmoothingInterpSpeed = 8.0f;
CineComp->SetFocusSettings(Focus);
CineComp->SetCurrentFocalLength(35.0f); // mm; UPROPERTY(Interp) so Sequencer can key it
CineComp->SetCurrentAperture(2.0f); // f-stop; also Interp
Cam->LookatTrackingSettings.bEnableLookAtTracking = true;
Cam->LookatTrackingSettings.ActorToTrack = TargetActor; // TSoftObjectPtr<AActor>
Cam->LookatTrackingSettings.RelativeOffset = FVector(0.f, 0.f, 80.f);
Cam->LookatTrackingSettings.LookAtTrackingInterpSpeed = 4.0f;
CurrentFocusDistance 和 CurrentHorizontalFOV 只能读取;要查询视野,请使用 GetHorizontalFieldOfView() 和 GetVerticalFieldOfView()。预设通过 SetFilmbackPresetByName、SetLensPresetByName 和 SetCropPresetByName 设置。
将摄像机附加到机架,并在 Sequencer 中为机架的 Interp 属性设置关键帧,而不是手动为摄像机变换设置动画:
#include "CameraRig_Rail.h"
#include "CameraRig_Crane.h"
Rail->CurrentPositionOnRail = 0.35f; // 0..1 along the spline
Rail->bLockOrientationToRail = true;
USplineComponent* RailSpline = Rail->GetRailSplineComponent();
Crane->CraneArmLength = 400.0f; // cm
Crane->CranePitch = 12.0f; // degrees
Crane->CraneYaw = -45.0f;
Crane->bLockMountPitch = true; // also bLockMountYaw
两个机架都重写了 GetDefaultAttachComponent(),因此将摄像机作为子对象附加后,它会位于正确的安装位置。
Movie Render Graph
Movie Render Graph 已在 5.8 中达到生产就绪状态,新项目应优先采用。UMovieGraphConfig 是由 UMovieGraphNode 子类组成的节点图(设置使用 UMovieGraphSettingNode,渲染通道使用 UMovieGraphRenderPassNode,分辨率和输出路径使用 UMovieGraphGlobalOutputSettingNode);UMovieGraphPipeline 通过 Initialize(UMoviePipelineExecutorJob*, const FMovieGraphInitConfig&) 执行该图。
运行时渲染通过 UMoviePipelineQueueEngineSubsystem 进行,这是 MovieRenderPipelineCore 中的 UEngineSubsystem。面向编辑器的 UMoviePipelineQueueSubsystem 是 MovieRenderPipelineEditor 中的 UEditorSubsystem,不能在运行时代码中引用——否则会导致打包构建失败。
#include "MoviePipelineQueueEngineSubsystem.h"
#include "MoviePipelineQueue.h"
#include "Graph/MovieGraphConfig.h"
UMoviePipelineQueueEngineSubsystem* RenderSubsystem =
GEngine->GetEngineSubsystem<UMoviePipelineQueueEngineSubsystem>();
if (!RenderSubsystem || RenderSubsystem->IsRendering())
{
return;
}
UMoviePipelineExecutorJob* Job = RenderSubsystem->AllocateJob(ShotSequence);
Job->JobName = TEXT("Shot_0010");
Job->Map = FSoftObjectPath(GetWorld());
Job->SetGraphPreset(RenderGraphAsset); // UMovieGraphConfig*
RenderSubsystem->OnRenderFinished.AddDynamic(this, &AMyRenderDirector::HandleRenderFinished);
RenderSubsystem->RenderJob(Job);
AllocateJob 会清空队列,因此只会渲染一个作业;如需批处理,请为每个作业调用 GetQueue()->AllocateNewJob(UMoviePipelineExecutorJob::StaticClass()),然后调用 RenderQueueWithExecutor(UMoviePipelineInProcessExecutor::StaticClass())。自定义执行器可继承 UMoviePipelineExecutorBase(重写 Execute_Implementation 和 IsRendering_Implementation),也可继承 UMoviePipelineLinearExecutorBase;后者会遍历队列,只需由你实现 Start(const UMoviePipelineExecutorJob*)。
渲染层是世界功能:UMovieGraphRenderLayerSubsystem 是通过 UMovieGraphRenderLayerSubsystem::GetFromWorld(World) 获取的 UWorldSubsystem,其中持有 UMovieGraphRenderLayer 对象。使用 UMovieGraphRenderLayer::AddLayerModifier(UMovieGraphModifierBase*) 添加修饰器,使用 GetLayerModifiers() 读取(仅限 Blueprint——该方法未从 MinimalAPI 类导出,Graph/MovieGraphRenderLayerSubsystem.h:1216),使用 RemoveLayerModifier() 移除,并使用 SetActiveRenderLayerByName 或 ClearActiveRenderLayer 切换渲染层。
旧版 Movie Render Queue——仍随产品发布并受支持,但不是新图的默认选项。UMoviePipeline 是执行对象,由持有 UMoviePipelineSetting 对象的 UMoviePipelinePrimaryConfig 配置,可通过 FindOrAddSettingByClass / FindSettingByClass 获取。UMoviePipelineOutputSetting 位于 MovieRenderPipelineCore 中(OutputDirectory、FileNameFormat、OutputResolution、bUseCustomFrameRate、OutputFrameRate、ZeroPadFrameNumbers);通道和容器(UMoviePipelineDeferredPassBase、UMoviePipelineImageSequenceOutput_PNG、UMoviePipelineImageSequenceOutput_EXR)位于 MovieRenderPipelineRenderPasses 中,必须单独添加到 Build.cs。作业只能采用图配置(SetGraphPreset、IsUsingGraphConfiguration())或旧版配置(SetConfiguration、IsUsingBasicConfiguration())之一——不能同时使用两者。
DaySequence(5.8 中为 Experimental)基于 MovieScene 构建,用于处理一天中的时段;它是单独的资源类型,上述 API 无法直接用于它。
Deprecated — do not use
| Do not emit | Use in 5.8 | Source |
|---|---|---|
SeqActor->SequencePlayer | SeqActor->GetSequencePlayer() | UE_DEPRECATED(5.4) in LevelSequenceActor.h:86 |
SeqActor->bAutoPlay | SeqActor->PlaybackSettings.bAutoPlay | bAutoPlay_DEPRECATED in LevelSequenceActor.h:109 |
non-const MovieScene->GetBindings() | const GetBindings() | UE_DEPRECATED(5.7) in MovieScene.h:782 |
FMovieSceneBinding::GetName / SetName | FMovieScenePossessable::GetName, FMovieSceneSpawnable::GetName | UE_DEPRECATED(5.7) in MovieSceneBinding.h:89 |
MovieScene->GetSoloNodes() / GetMuteNodes() | FindDecoration | UE_DEPRECATED(5.7) in MovieScene.h:978 |
MovieScene->OnChannelChanged() | OnChannelChangedWithTime() | UE_DEPRECATED(5.8) in MovieScene.h:993 |
RenderLayer->AddModifier() / GetModifiers() / RemoveModifier() | AddLayerModifier() / GetLayerModifiers() / RemoveLayerModifier() | UE_DEPRECATED(5.7) in Graph/MovieGraphRenderLayerSubsystem.h:1204-1218 |
ConditionGroup->Evaluate() | EvaluateActorsAndComponents() | UE_DEPRECATED(5.6) in Graph/MovieGraphRenderLayerSubsystem.h:817 |
GetEffectiveOutputResolution() | GetOverscannedResolution() | UE_DEPRECATED(5.6) in MoviePipelineBlueprintLibrary.h:154 |
GameModeOverride | SoftGameModeOverride | UE_DEPRECATED(5.5) in MoviePipelineGameOverrideSetting.h:77 |
RendererName member | GetRendererName() | UE_DEPRECATED(5.7) in Graph/Nodes/MovieGraphBurnInNode.h:43 |
Section->Parameters.TimeScale = 1.0 | Parameters.TimeScale.Set(1.0) | explicit ctor, Variants/MovieSceneTimeWarpVariant.h:66 |
常见错误
在事件轨道的自由函数上使用 UFUNCTION:UFUNCTION 只能用于 UCLASS 或 USTRUCT 的主体内部,而且 Sequencer 会在导演实例上调用事件端点。将端点放在 ULevelSequenceDirector 子类上,不带参数,或带一个对象参数。
端点签名错误:void Foo(FName Tag, int32 Index) 永远不会绑定成功。引擎接受不带参数的函数,或带一个按值传递的对象/接口参数的函数,且不能有返回值。
**Sequencer 预览中没有触发任何内容:**非游戏世界会跳过缺少 CallInEditor 的 UFUNCTION 端点。
**在 Play() 后绑定:**第 0 帧已经根据资产绑定完成求值。请在调用 Play() 前,对 ALevelSequenceActor 调用 SetBindingByTag 或 SetBinding。
丢失生成的 Actor:CreateLevelSequencePlayer 会返回一个原始的 ALevelSequenceActor*。请将它和播放器存储在 UPROPERTY() 成员中,否则它们会在过场动画播放过程中被垃圾回收。
**镜头永远不会切回玩家:**只有当镜头切换轨道的片段解析为 Restore State 时,它才会恢复先前的视图目标(Level Sequences 默认采用此模式,BaseEngine.ini 中的 DefaultCompletionMode=RestoreState;恢复逻辑见 MovieSceneCameraCutGameHandler.cpp:115-124);停止时会退出电影模式(LevelSequencePlayer.cpp:177)。如果片段使用 Keep State、ForceKeepState 或 bPauseAtEnd,请处理 OnFinished,并自行调用 PC->SetViewTargetWithBlend(PC->GetPawn(), 0.5f, VTBlend_Cubic)。
**跳过后 Actor 停留在动作姿势中:**在调用 Stop() 前,设置 Settings.FinishCompletionStateOverride = EMovieSceneCompletionModeOverride::ForceRestoreState,或调用 SetCompletionModeOverride。
**从游戏代码访问 UMoviePipelineQueueSubsystem:**它是 MovieRenderPipelineEditor 中的 UEditorSubsystem。运行时渲染应使用 MovieRenderPipelineCore 中的 UMoviePipelineQueueEngineSubsystem。
在同一作业中混用图表配置和旧版配置:SetGraphPreset 与 SetConfiguration 互斥。请先检查 IsUsingGraphConfiguration(),再判断 GetConfiguration() 是否有效。
帧率混淆:SetFrameRange 使用显示帧率的帧,而 UMovieSceneSubSection 偏移和 UMovieScene::GetPlaybackRange 使用滴答分辨率的帧。请使用 GetDisplayRate() 和 GetTickResolution() 进行转换。
**以为镜头切换会复制:**每个客户端都会单独评估镜头切换。使用 SetReplicatePlayback(true) 或 AReplicatedLevelSequenceActor,让服务器驱动播放时间,并让每个客户端应用自己的镜头切换。
相关技能
ue-animation-system— 骨骼动画资产、蒙太奇,以及序列动画轨道播放的动画通知ue-gameplay-cameras— Sequencer 之外的游戏镜头、镜头修改器、镜头震动和视图目标混合ue-audio-system— 序列音频轨道所依赖的声音资产、子混音和衰减ue-niagara-effects— 电影化内容触发或序列设置关键帧的粒子系统ue-materials-rendering— 渲染通道捕获的后期处理、Lumen 和材质设置ue-actor-component-architecture— 生成序列控制的 Actor 并管理其所有权ue-world-level-streaming— 在过场动画前流式加载关卡,以及渲染期间的数据层状态