mcpField
U
ue-sequencer-cinematics

ue-sequencer-cinematics

github.com/quodsoler创意与媒体4191.1k 次安装4 周前更新
代码仓库

关于 ue-sequencer-cinematics

面向 Unreal Engine 5.8 开发者的 Sequencer 与电影化工作流技能,提供经 5.8 头文件核对的运行时和编辑器 API 指引,涵盖播放、绑定、事件轨道及渲染。

主要功能

  1. 01Sequencer 模块依赖指引
  2. 02运行时播放与绑定
  3. 03事件轨道调用规则
  4. 04MovieScene 数据模型说明
  5. 05电影摄影机与渲染指引

适用场景

  1. 01实现游戏内过场动画播放
  2. 02将序列绑定到运行时 Actor
  3. 03从时间轴事件调用 C++
  4. 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运行时
覆盖绑定所解析到的 ActorALevelSequenceActor::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)动画对象
UMovieScene3DTransformTrackActor 和组件变换
UMovieSceneSkeletalAnimationTrack骨骼网格体动画
UMovieSceneCameraCutTrack视口使用的摄像机
UMovieSceneEventTrackDirector 函数调用
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 emitUse in 5.8Source
SeqActor->SequencePlayerSeqActor->GetSequencePlayer()UE_DEPRECATED(5.4) in LevelSequenceActor.h:86
SeqActor->bAutoPlaySeqActor->PlaybackSettings.bAutoPlaybAutoPlay_DEPRECATED in LevelSequenceActor.h:109
non-const MovieScene->GetBindings()const GetBindings()UE_DEPRECATED(5.7) in MovieScene.h:782
FMovieSceneBinding::GetName / SetNameFMovieScenePossessable::GetName, FMovieSceneSpawnable::GetNameUE_DEPRECATED(5.7) in MovieSceneBinding.h:89
MovieScene->GetSoloNodes() / GetMuteNodes()FindDecorationUE_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
GameModeOverrideSoftGameModeOverrideUE_DEPRECATED(5.5) in MoviePipelineGameOverrideSetting.h:77
RendererName memberGetRendererName()UE_DEPRECATED(5.7) in Graph/Nodes/MovieGraphBurnInNode.h:43
Section->Parameters.TimeScale = 1.0Parameters.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 — 在过场动画前流式加载关卡,以及渲染期间的数据层状态

评论

支持 Markdown