ue-sequencer-cinematics
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSkill: ue-sequencer-cinematics
技能:ue-sequencer-cinematics
You are an expert in Unreal Engine's Sequencer and cinematic systems.
你是Unreal Engine的Sequencer和镜头系统专家。
Context Check
上下文检查
Read before writing any cinematic code for:
.agents/ue-project-context.md- Target UE version (API availability varies — SequencePlayer property deprecated in 5.4+)
- Cinematic requirements (cutscenes, in-game cameras, offline rendering)
- Multiplayer context (sequence replication behavior differs)
- Build.cs modules already declared
在编写任何镜头代码之前,请阅读,了解以下内容:
.agents/ue-project-context.md- 目标UE版本(API可用性因版本而异——SequencePlayer属性在5.4+中已被弃用)
- 镜头需求(过场动画、游戏内镜头、离线渲染)
- 多人游戏上下文(序列同步行为不同)
- 已声明的Build.cs模块
Information Gathering
信息收集
Ask for:
- Cinematic type: full-screen cutscene, in-game camera, or background ambient sequence
- Whether actors bind at runtime or are pre-placed in the level
- Whether camera control must return to the player after playback
- One-shot or looping sequence
- Real-time gameplay or offline Movie Render Queue output
请询问以下信息:
- 镜头类型:全屏过场动画、游戏内镜头还是背景环境序列
- 角色是在运行时绑定还是预先放置在关卡中
- 播放结束后是否需要将镜头控制权交还给玩家
- 是一次性播放还是循环播放序列
- 是实时游戏还是离线Movie Render Queue输出
Build.cs Modules
Build.cs模块
csharp
PublicDependencyModuleNames.AddRange(new string[]
{
"LevelSequence", "MovieScene", "CinematicCamera",
});
// Offline rendering only:
PrivateDependencyModuleNames.Add("MovieRenderPipelineCore");csharp
PublicDependencyModuleNames.AddRange(new string[]
{
"LevelSequence", "MovieScene", "CinematicCamera",
});
// 仅离线渲染时添加:
PrivateDependencyModuleNames.Add("MovieRenderPipelineCore");Playing Level Sequences
播放Level Sequence
ALevelSequenceActor — World-Placed
ALevelSequenceActor — 放置于世界中
ALevelSequenceActorGetSequencePlayer()SequencePlayercpp
// LevelSequenceActor.h: ULevelSequencePlayer* GetSequencePlayer() const;
ULevelSequencePlayer* Player = SeqActor->GetSequencePlayer();
if (Player) { Player->Play(); }ALevelSequenceActorGetSequencePlayer()SequencePlayercpp
// LevelSequenceActor.h: ULevelSequencePlayer* GetSequencePlayer() const;
ULevelSequencePlayer* Player = SeqActor->GetSequencePlayer();
if (Player) { Player->Play(); }ULevelSequencePlayer::CreateLevelSequencePlayer — Runtime Spawn
ULevelSequencePlayer::CreateLevelSequencePlayer — 运行时生成
cpp
// LevelSequencePlayer.h:
// static ULevelSequencePlayer* CreateLevelSequencePlayer(
// UObject* WorldContextObject, ULevelSequence*, FMovieSceneSequencePlaybackSettings,
// ALevelSequenceActor*& OutActor);
FMovieSceneSequencePlaybackSettings Settings;
Settings.bAutoPlay = false;
Settings.PlayRate = 1.0f;
Settings.LoopCount.Value = 0; // 0=once, -1=infinite
Settings.bDisableMovementInput = true;
Settings.bDisableLookAtInput = true;
Settings.bHidePlayer = false;
Settings.bHideHud = false;
Settings.bDisableCameraCuts = false;
Settings.bPauseAtEnd = false;
Settings.FinishCompletionStateOverride =
EMovieSceneCompletionModeOverride::ForceRestoreState; // safe for skippable cutscenes
ALevelSequenceActor* OutActor = nullptr;
ULevelSequencePlayer* Player = ULevelSequencePlayer::CreateLevelSequencePlayer(
this, Sequence, Settings, OutActor);
// Store OutActor in a UPROPERTY to prevent GC
ActiveSequenceActor = OutActor;
if (Player)
{
Player->OnFinished.AddDynamic(this, &AMyClass::OnCutsceneFinished);
Player->Play();
}cpp
// LevelSequencePlayer.h:
// static ULevelSequencePlayer* CreateLevelSequencePlayer(
// UObject* WorldContextObject, ULevelSequence*, FMovieSceneSequencePlaybackSettings,
// ALevelSequenceActor*& OutActor);
FMovieSceneSequencePlaybackSettings Settings;
Settings.bAutoPlay = false;
Settings.PlayRate = 1.0f;
Settings.LoopCount.Value = 0; // 0=播放一次,-1=无限循环
Settings.bDisableMovementInput = true;
Settings.bDisableLookAtInput = true;
Settings.bHidePlayer = false;
Settings.bHideHud = false;
Settings.bDisableCameraCuts = false;
Settings.bPauseAtEnd = false;
Settings.FinishCompletionStateOverride =
EMovieSceneCompletionModeOverride::ForceRestoreState; // 适用于可跳过的过场动画
ALevelSequenceActor* OutActor = nullptr;
ULevelSequencePlayer* Player = ULevelSequencePlayer::CreateLevelSequencePlayer(
this, Sequence, Settings, OutActor);
// 将OutActor存储在UPROPERTY中以防止被垃圾回收
ActiveSequenceActor = OutActor;
if (Player)
{
Player->OnFinished.AddDynamic(this, &AMyClass::OnCutsceneFinished);
Player->Play();
}Play Control (UMovieSceneSequencePlayer base)
播放控制(基于UMovieSceneSequencePlayer)
cpp
// MovieSceneSequencePlayer.h
Player->Play();
Player->PlayReverse();
Player->PlayLooping(-1); // -1 = infinite loops
Player->Pause();
Player->Stop(); // moves cursor to end, fires OnStop
Player->StopAtCurrentTime();
Player->GoToEndAndStop();
Player->SetPlayRate(0.5f); // negative = reverse
// Jump to frame (skips events between current and target)
// Blueprint exposes this as GoToFrame. In C++, use SetPlaybackPosition with Jump.
Player->SetPlaybackPosition(
FMovieSceneSequencePlaybackParams(FFrameTime(120), EUpdatePositionMethod::Jump));
// Play through to frame (triggers all events along the way)
Player->PlayTo(
FMovieSceneSequencePlaybackParams(FFrameTime(240), EUpdatePositionMethod::Play),
FMovieSceneSequencePlayToParams());
// Restrict play range
Player->SetFrameRange(0, 60); // frames 0–60
Player->SetTimeRange(0.0f, 2.5f); // seconds
// State query
bool bPlaying = Player->IsPlaying();
FQualifiedFrameTime Now = Player->GetCurrentTime();
FQualifiedFrameTime Dur = Player->GetDuration();
// Delegates (bind before Play)
Player->OnFinished.AddDynamic(this, &UMyClass::OnSeqFinished);
Player->OnPlay.AddDynamic(this, &UMyClass::OnSeqPlay);
Player->OnStop.AddDynamic(this, &UMyClass::OnSeqStop);
Player->OnNativeFinished.BindUObject(this, &UMyClass::OnNativeFinished); // non-dynamic
// Camera cut event (LevelSequencePlayer.h)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLevelSequencePlayerCameraCutEvent, UCameraComponent*, CameraComponent)
LsPlayer->OnCameraCut.AddDynamic(this, &UMyClass::OnCameraCut);
// Restore state on early stop (skippable cutscene)
Player->SetCompletionModeOverride(EMovieSceneCompletionModeOverride::ForceRestoreState);
Player->Stop();
// Sub-sequence snapshot
FLevelSequencePlayerSnapshot Snap;
Player->TakeFrameSnapshot(Snap);
// Snap.CurrentShotName, Snap.RootTime, Snap.CameraComponent, Snap.ActiveShotcpp
// MovieSceneSequencePlayer.h
Player->Play();
Player->PlayReverse();
Player->PlayLooping(-1); // -1 = 无限循环
Player->Pause();
Player->Stop(); // 将播放指针移至末尾,触发OnStop
Player->StopAtCurrentTime();
Player->GoToEndAndStop();
Player->SetPlayRate(0.5f); // 负值为倒放
// 跳转到指定帧(跳过当前帧与目标帧之间的所有事件)
// 蓝图中此功能为GoToFrame,在C++中使用SetPlaybackPosition并指定Jump方式
Player->SetPlaybackPosition(
FMovieSceneSequencePlaybackParams(FFrameTime(120), EUpdatePositionMethod::Jump));
// 播放到指定帧(触发范围内的所有事件)
Player->PlayTo(
FMovieSceneSequencePlaybackParams(FFrameTime(240), EUpdatePositionMethod::Play),
FMovieSceneSequencePlayToParams());
// 限制播放范围
Player->SetFrameRange(0, 60); // 帧范围0–60
Player->SetTimeRange(0.0f, 2.5f); // 时间范围0.0–2.5秒
// 状态查询
bool bPlaying = Player->IsPlaying();
FQualifiedFrameTime Now = Player->GetCurrentTime();
FQualifiedFrameTime Dur = Player->GetDuration();
// 委托(需在Play()之前绑定)
Player->OnFinished.AddDynamic(this, &UMyClass::OnSeqFinished);
Player->OnPlay.AddDynamic(this, &UMyClass::OnSeqPlay);
Player->OnStop.AddDynamic(this, &UMyClass::OnSeqStop);
Player->OnNativeFinished.BindUObject(this, &UMyClass::OnNativeFinished); // 非动态委托
// 镜头切换事件(LevelSequencePlayer.h)
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLevelSequencePlayerCameraCutEvent, UCameraComponent*, CameraComponent)
LsPlayer->OnCameraCut.AddDynamic(this, &UMyClass::OnCameraCut);
// 提前停止时恢复状态(适用于可跳过的过场动画)
Player->SetCompletionModeOverride(EMovieSceneCompletionModeOverride::ForceRestoreState);
Player->Stop();
// 子序列快照
FLevelSequencePlayerSnapshot Snap;
Player->TakeFrameSnapshot(Snap);
// Snap.CurrentShotName, Snap.RootTime, Snap.CameraComponent, Snap.ActiveShotActor Binding
Actor绑定
Tag bindings in Sequencer (right-click object binding -> Tags...) then override at runtime.
Always bind before calling .
Play()在Sequencer中为绑定添加标签(右键对象绑定 → 标签...),然后在运行时覆盖。务必在调用之前完成绑定。
Play()Spawnables vs Possessables
Spawnables与Possessables
Possessables bind to pre-existing world actors (placed in level or spawned by gameplay). Spawnables are actors the sequence itself creates and destroys.
cpp
// Spawnable: sequence owns the actor lifecycle
// Set in Sequencer editor: right-click actor track → "Change to Spawnable"
// At runtime, actor spawns when sequence reaches its range, despawns when exiting
// Dynamic possessable: bind a gameplay-spawned actor to a sequence track
// Create the binding ID in the editor, then override at runtime:
FMovieSceneObjectBindingID BindingID = /* from sequence editor */;
ALevelSequenceActor* SeqActor = /* your sequence actor */;
SeqActor->SetBinding(BindingID, {SpawnedActor});Why this matters: Use possessables for persistent world actors (doors, elevators) and spawnables for transient cutscene-only actors (cinematic-only characters, props). Possessables survive sequence end; spawnables are cleaned up automatically.
cpp
// LevelSequenceActor.h — all binding API lives here
// Replace bound actors (preferred: tag-based, resilient to GUID changes)
SeqActor->SetBindingByTag(FName("Hero"), TArray<AActor*>{ HeroActor },
/*bAllowBindingsFromAsset=*/ false);
// GUID-based (expose FMovieSceneObjectBindingID via UPROPERTY for editor assignment)
// UPROPERTY(EditAnywhere) FMovieSceneObjectBindingID HeroBindingID;
SeqActor->SetBinding(HeroBindingID, TArray<AActor*>{ HeroActor }, false);
// Append without removing existing bindings
SeqActor->AddBindingByTag(FName("NPC"), NpcActor, /*bAllowBindingsFromAsset=*/ true);
// Remove / reset
SeqActor->RemoveBindingByTag(FName("NPC"), NpcActor);
SeqActor->ResetBinding(HeroBindingID); // revert to asset binding
SeqActor->ResetBindings(); // revert all overrides
// Lookup by tag
FMovieSceneObjectBindingID ID = SeqActor->FindNamedBinding(FName("Hero"));
const TArray<FMovieSceneObjectBindingID>& All = SeqActor->FindNamedBindings(FName("NPC"));
// Inspect what is currently bound
TArray<UObject*> Bound = Player->GetBoundObjects(HeroBindingID);
// FMovieSceneObjectBindingID (MovieSceneObjectBindingID.h):
// Access via public accessors — internal fields are private:
// GetGuid() — FGuid identifying the binding track
// GetRelativeSequenceID() — which sub-sequence holds it (0 = local)Possessables绑定到已存在的世界Actor(放置在关卡中或由游戏逻辑生成)。Spawnables是由序列自身创建和销毁的Actor。
cpp
// Spawnable:序列拥有Actor的生命周期
// 在Sequencer编辑器中设置:右键Actor轨道 → "切换为Spawnable"
// 运行时,Actor会在序列到达其时间范围时生成,离开时间范围时销毁
// 动态Possessable:将游戏逻辑生成的Actor绑定到序列轨道
// 在编辑器中创建绑定ID,然后在运行时覆盖:
FMovieSceneObjectBindingID BindingID = /* 来自序列编辑器 */;
ALevelSequenceActor* SeqActor = /* 你的序列Actor */;
SeqActor->SetBinding(BindingID, {SpawnedActor});为何区分:对持久化世界Actor(门、电梯)使用Possessables,对仅用于过场的临时Actor(仅镜头角色、道具)使用Spawnables。Possessables在序列结束后保留;Spawnables会被自动清理。
cpp
// LevelSequenceActor.h — 所有绑定API都在此
// 替换绑定的Actor(推荐:基于标签,可应对GUID变更)
SeqActor->SetBindingByTag(FName("Hero"), TArray<AActor*>{ HeroActor },
/*bAllowBindingsFromAsset=*/ false);
// 基于GUID(通过UPROPERTY暴露FMovieSceneObjectBindingID以便在编辑器中赋值)
// UPROPERTY(EditAnywhere) FMovieSceneObjectBindingID HeroBindingID;
SeqActor->SetBinding(HeroBindingID, TArray<AActor*>{ HeroActor }, false);
// 追加绑定而不移除现有绑定
SeqActor->AddBindingByTag(FName("NPC"), NpcActor, /*bAllowBindingsFromAsset=*/ true);
// 移除/重置绑定
SeqActor->RemoveBindingByTag(FName("NPC"), NpcActor);
SeqActor->ResetBinding(HeroBindingID); // 恢复为资源中的绑定
SeqActor->ResetBindings(); // 恢复所有覆盖的绑定
// 通过标签查找
FMovieSceneObjectBindingID ID = SeqActor->FindNamedBinding(FName("Hero"));
const TArray<FMovieSceneObjectBindingID>& All = SeqActor->FindNamedBindings(FName("NPC"));
// 检查当前绑定的对象
TArray<UObject*> Bound = Player->GetBoundObjects(HeroBindingID);
// FMovieSceneObjectBindingID (MovieSceneObjectBindingID.h):
// 通过公共访问器访问——内部字段为私有:
// GetGuid() — 标识绑定轨道的FGuid
// GetRelativeSequenceID() — 子序列的ID(0表示本地)Camera System
镜头系统
ACineCameraActor / UCineCameraComponent
ACineCameraActor / UCineCameraComponent
cpp
// CineCameraActor.h: UCineCameraComponent* GetCineCameraComponent() const;
// CineCameraComponent.h / CineCameraSettings.h:
// FCameraFilmbackSettings Filmback (SensorWidth, SensorHeight in mm, read-only SensorAspectRatio)
// FCameraLensSettings LensSettings (MinFocalLength, MaxFocalLength, MinFStop, MaxFStop mm)
// FCameraFocusSettings FocusSettings (FocusMethod, ManualFocusDistance cm, bSmoothFocusChanges)
// float CurrentFocalLength — Interp, animatable in Sequencer
// float CurrentAperture — f-stop, Interp-animatable
ACineCameraActor* Cam = GetWorld()->SpawnActor<ACineCameraActor>(SpawnTransform);
UCineCameraComponent* CC = Cam->GetCineCameraComponent();
FCameraFilmbackSettings FB;
FB.SensorWidth = 36.0f; FB.SensorHeight = 24.0f; // full-frame 35mm
CC->SetFilmback(FB);
CC->SetCurrentFocalLength(50.0f); // mm
CC->SetCurrentAperture(2.0f); // f-stop
FCameraFocusSettings FS;
FS.FocusMethod = ECameraFocusMethod::Manual; // Manual | Tracking | Disable | DoNotOverride
FS.ManualFocusDistance = 500.0f; // cm
FS.bSmoothFocusChanges = true;
CC->SetFocusSettings(FS);
// Lookat tracking (CineCameraActor.h: FCameraLookatTrackingSettings LookatTrackingSettings)
Cam->LookatTrackingSettings.bEnableLookAtTracking = true;
Cam->LookatTrackingSettings.ActorToTrack = TargetActor;
Cam->LookatTrackingSettings.LookAtTrackingInterpSpeed = 5.0f;
Cam->LookatTrackingSettings.RelativeOffset = FVector(0, 0, 90.f);
// Prevent sequence from overriding gameplay camera (set before Play)
SeqActor->PlaybackSettings.bDisableCameraCuts = true;
// Restore player camera after cutscene (call from OnFinished delegate)
APlayerController* PC = GetWorld()->GetFirstPlayerController();
PC->SetViewTargetWithBlend(PC->GetPawn(), 0.5f, VTBlend_Cubic);
PC->SetIgnoreMoveInput(false);
PC->SetIgnoreLookInput(false);cpp
// CineCameraActor.h: UCineCameraComponent* GetCineCameraComponent() const;
// CineCameraComponent.h / CineCameraSettings.h:
// FCameraFilmbackSettings Filmback (SensorWidth、SensorHeight单位为毫米,只读的SensorAspectRatio)
// FCameraLensSettings LensSettings (MinFocalLength、MaxFocalLength、MinFStop、MaxFStop单位为毫米)
// FCameraFocusSettings FocusSettings (FocusMethod、ManualFocusDistance单位为厘米,bSmoothFocusChanges)
// float CurrentFocalLength — 可插值,可在Sequencer中动画
// float CurrentAperture — f值,可插值动画
ACineCameraActor* Cam = GetWorld()->SpawnActor<ACineCameraActor>(SpawnTransform);
UCineCameraComponent* CC = Cam->GetCineCameraComponent();
FCameraFilmbackSettings FB;
FB.SensorWidth = 36.0f; FB.SensorHeight = 24.0f; // 全画幅35mm
CC->SetFilmback(FB);
CC->SetCurrentFocalLength(50.0f); // 毫米
CC->SetCurrentAperture(2.0f); // f值
FCameraFocusSettings FS;
FS.FocusMethod = ECameraFocusMethod::Manual; // Manual | Tracking | Disable | DoNotOverride
FS.ManualFocusDistance = 500.0f; // 厘米
FS.bSmoothFocusChanges = true;
CC->SetFocusSettings(FS);
// 看向跟踪(CineCameraActor.h: FCameraLookatTrackingSettings LookatTrackingSettings)
Cam->LookatTrackingSettings.bEnableLookAtTracking = true;
Cam->LookatTrackingSettings.ActorToTrack = TargetActor;
Cam->LookatTrackingSettings.LookAtTrackingInterpSpeed = 5.0f;
Cam->LookatTrackingSettings.RelativeOffset = FVector(0, 0, 90.f);
// 防止序列覆盖游戏镜头(在Play()之前设置)
SeqActor->PlaybackSettings.bDisableCameraCuts = true;
// 过场结束后恢复玩家镜头(从OnFinished委托中调用)
APlayerController* PC = GetWorld()->GetFirstPlayerController();
PC->SetViewTargetWithBlend(PC->GetPawn(), 0.5f, VTBlend_Cubic);
PC->SetIgnoreMoveInput(false);
PC->SetIgnoreLookInput(false);APlayerCameraManager
APlayerCameraManager
APlayerCameraManagerPlayerController->PlayerCameraManagercpp
APlayerController* PC = GetWorld()->GetFirstPlayerController();
// PlayerCameraManager handles blend state; SetViewTargetWithBlend triggers it.
PC->SetViewTargetWithBlend(PC->GetPawn(), 0.5f, VTBlend_Cubic);
// The blend is processed each tick inside APlayerCameraManager::UpdateCamera.APlayerCameraManagerPlayerController->PlayerCameraManagercpp
APlayerController* PC = GetWorld()->GetFirstPlayerController();
// PlayerCameraManager处理混合状态;SetViewTargetWithBlend触发混合
PC->SetViewTargetWithBlend(PC->GetPawn(), 0.5f, VTBlend_Cubic);
// 混合在APlayerCameraManager::UpdateCamera的每帧中处理Sequencer Events
Sequencer事件
Event tracks call s on objects in the event context.
Default event context: + .
UFUNCTIONUWorldALevelScriptActorcpp
// Function must be UFUNCTION(BlueprintCallable) on a context object
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void TriggerExplosion()
{
ExplosionSystem->SpawnExplosion(ExplosionLocation);
}
// Trigger C++ code at a specific frame by playing to it (fires all events in range)
Player->PlayTo(
FMovieSceneSequencePlaybackParams(FFrameTime(60), EUpdatePositionMethod::Play),
FMovieSceneSequencePlayToParams());事件轨道会调用事件上下文中对象的。默认事件上下文: + 。
UFUNCTIONUWorldALevelScriptActorcpp
// 函数必须是上下文对象上的UFUNCTION(BlueprintCallable)
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void TriggerExplosion()
{
ExplosionSystem->SpawnExplosion(ExplosionLocation);
}
// 通过播放到指定帧来触发C++代码(触发范围内的所有事件)
Player->PlayTo(
FMovieSceneSequencePlaybackParams(FFrameTime(60), EUpdatePositionMethod::Play),
FMovieSceneSequencePlayToParams());FMovieSceneEvent
FMovieSceneEvent
FMovieSceneEvent- — the master track added to a binding or as a master track
UMovieSceneEventTrack - — a section containing one or more trigger entries
UMovieSceneEventTriggerSection - — each entry inside the trigger section, pointing to the endpoint function
FMovieSceneEvent
The endpoint function is resolved at runtime against the event context objects (by default
and ). Director-based events resolve against a
subclass instance.
UWorldALevelScriptActorULevelSequenceDirectorFMovieSceneEvent- — 添加到绑定或作为主轨道的主轨道
UMovieSceneEventTrack - — 包含一个或多个触发条目的区段
UMovieSceneEventTriggerSection - — 触发区段内的每个条目,指向端点函数
FMovieSceneEvent
端点函数会在运行时根据事件上下文对象(默认是和)解析。基于导演的事件会针对子类实例解析。
UWorldALevelScriptActorULevelSequenceDirectorULevelSequenceDirector — Custom Event Context
ULevelSequenceDirector — 自定义事件上下文
ULevelSequenceDirectorcpp
// MySequenceDirector.h
#include "LevelSequenceDirector.h"
#include "MySequenceDirector.generated.h"
UCLASS(Blueprintable)
class UMySequenceDirector : public ULevelSequenceDirector
{
GENERATED_BODY()
public:
// Called from Sequencer event tracks — bind to event key in the Sequencer editor
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void OnDialogueStart(FName SpeakerTag);
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void OnCutsceneChoice(int32 ChoiceIndex);
};
// MySequenceDirector.cpp
void UMySequenceDirector::OnDialogueStart(FName SpeakerTag)
{
// Access the sequence player and bound actors from within the Director.
// ULevelSequenceDirector.h: UPROPERTY ULevelSequencePlayer* Player (direct field, no getter)
TArray<UObject*> Bound = Player->GetBoundObjects(SpeakerBindingID);
// Trigger gameplay logic: UI, dialogue system, camera focus, etc.
}Why Director over Level Script: The Director travels with the sequence asset, not the level.
Reusable across maps. Supports per-sequence state (member variables). Level Script events
only work when the sequence is placed in that specific level.
ULevelSequenceDirectorcpp
// MySequenceDirector.h
#include "LevelSequenceDirector.h"
#include "MySequenceDirector.generated.h"
UCLASS(Blueprintable)
class UMySequenceDirector : public ULevelSequenceDirector
{
GENERATED_BODY()
public:
// 从Sequencer事件轨道调用——在Sequencer编辑器中绑定到事件关键帧
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void OnDialogueStart(FName SpeakerTag);
UFUNCTION(BlueprintCallable, Category = "Cinematics")
void OnCutsceneChoice(int32 ChoiceIndex);
};
// MySequenceDirector.cpp
void UMySequenceDirector::OnDialogueStart(FName SpeakerTag)
{
// 在导演类中访问序列播放器和绑定的Actor。
// ULevelSequenceDirector.h: UPROPERTY ULevelSequencePlayer* Player(直接字段,无getter)
TArray<UObject*> Bound = Player->GetBoundObjects(SpeakerBindingID);
// 触发游戏逻辑:UI、对话系统、镜头对焦等。
}为何选择导演类而非关卡脚本:导演类随序列资源移动,不依赖关卡。可在多个地图中复用。支持每个序列的状态(成员变量)。关卡脚本事件仅在序列放置于特定关卡时生效。
MovieScene Tracks
MovieScene轨道
cpp
// MovieScene.h — get from the LevelSequence asset
UMovieScene* MS = SeqActor->GetSequence()->GetMovieScene();
// Possessables (world actors) — iterate by index
for (int32 i = 0; i < MS->GetPossessableCount(); ++i)
{
const FMovieScenePossessable& P = MS->GetPossessable(i);
}
// Spawnables (sequence-owned actors) — iterate by index
for (int32 i = 0; i < MS->GetSpawnableCount(); ++i)
{
const FMovieSceneSpawnable& S = MS->GetSpawnable(i);
}
// Master tracks (not bound to any actor)
const TArray<UMovieSceneTrack*>& Masters = MS->GetTracks();
// Tracks on a specific binding
const FMovieSceneBinding* B = MS->FindBinding(SomeGuid);
if (B) { for (UMovieSceneTrack* T : B->GetTracks()) { /* cast to subtype */ } }| Track Class | Purpose |
|---|---|
| Transform animation |
| Skeletal mesh animation |
| Event triggers |
| Audio |
| Screen fade |
| Camera cuts |
| Sub-sequences |
| Arbitrary UPROPERTY animation (base class) |
All track types require in Build.cs.
MovieSceneTracksCustom tracks: subclass + for domain-specific
animation data. Register via . This is an advanced
pattern — most needs are met by subclasses.
UMovieSceneTrackUMovieSceneSectionISequencerModule::RegisterTrackEditorUMovieScenePropertyTrackUMovieScenePropertyTrackUPROPERTYUMovieSceneFloatTrackUMovieSceneBoolTrackUMovieSceneColorTrackUMovieSceneFloatSectionFMovieSceneFloatChannelcpp
// MovieScene.h — 从LevelSequence资源获取
UMovieScene* MS = SeqActor->GetSequence()->GetMovieScene();
// Possessables(世界Actor)——按索引遍历
for (int32 i = 0; i < MS->GetPossessableCount(); ++i)
{
const FMovieScenePossessable& P = MS->GetPossessable(i);
}
// Spawnables(序列拥有的Actor)——按索引遍历
for (int32 i = 0; i < MS->GetSpawnableCount(); ++i)
{
const FMovieSceneSpawnable& S = MS->GetSpawnable(i);
}
// 主轨道(不绑定到任何Actor)
const TArray<UMovieSceneTrack*>& Masters = MS->GetTracks();
// 特定绑定的轨道
const FMovieSceneBinding* B = MS->FindBinding(SomeGuid);
if (B) { for (UMovieSceneTrack* T : B->GetTracks()) { /* 转换为子类型 */ } }| 轨道类 | 用途 |
|---|---|
| 变换动画 |
| 骨骼网格动画 |
| 事件触发 |
| 音频 |
| 屏幕淡入淡出 |
| 镜头切换 |
| 子序列 |
| 任意UPROPERTY动画(基类) |
所有轨道类型都需要在Build.cs中添加模块。
MovieSceneTracks自定义轨道:继承 + 以实现领域特定的动画数据。通过注册。这是高级模式——大多数需求可通过的子类满足。
UMovieSceneTrackUMovieSceneSectionISequencerModule::RegisterTrackEditorUMovieScenePropertyTrackUMovieScenePropertyTrackUPROPERTYUMovieSceneFloatTrackUMovieSceneBoolTrackUMovieSceneColorTrackUMovieSceneFloatSectionFMovieSceneFloatChannelSub-Sequences
子序列
cpp
// Add a sub-sequence track to a master UMovieScene
UMovieScene* MasterMS = MasterSequence->GetMovieScene();
UMovieSceneSubTrack* SubTrack = MasterMS->AddTrack<UMovieSceneSubTrack>();
// Add a child sequence — AddSequence(Sequence, StartFrame, Duration)
FFrameRate DisplayRate = MasterMS->GetDisplayRate();
FFrameNumber Start = (2.0 * DisplayRate).FloorToFrame(); // 2 seconds in
int32 Duration = (5.0 * DisplayRate).FloorToFrame().Value; // 5 seconds long
UMovieSceneSubSection* SubSection =
SubTrack->AddSequence(ChildLevelSequence, Start, Duration);
// Configure sub-section timing
SubSection->Parameters.TimeScale = 1.0; // FMovieSceneTimeWarpVariant (double), playback speed multiplier
SubSection->Parameters.bCanLoop = false;UMovieSceneSubTrackAddTrackSequenceIDFMovieSceneObjectBindingID::ResolveParentIndexMovieSceneTrackscpp
// 为主UMovieScene添加子序列轨道
UMovieScene* MasterMS = MasterSequence->GetMovieScene();
UMovieSceneSubTrack* SubTrack = MasterMS->AddTrack<UMovieSceneSubTrack>();
// 添加子序列——AddSequence(Sequence, StartFrame, Duration)
FFrameRate DisplayRate = MasterMS->GetDisplayRate();
FFrameNumber Start = (2.0 * DisplayRate).FloorToFrame(); // 2秒处
int32 Duration = (5.0 * DisplayRate).FloorToFrame().Value; // 时长5秒
UMovieSceneSubSection* SubSection =
SubTrack->AddSequence(ChildLevelSequence, Start, Duration);
// 配置子区段的时间
SubSection->Parameters.TimeScale = 1.0; // FMovieSceneTimeWarpVariant(双精度),播放速度倍数
SubSection->Parameters.bCanLoop = false;UMovieSceneSubTrackAddTrackSequenceIDFMovieSceneObjectBindingID::ResolveParentIndexMovieSceneTracksTime Dilation and SlowMo
时间 dilation与慢动作
For SlowMo effects during sequences, use on the sequence player —
this is independent of and does not affect world
physics or other gameplay systems. Combine with a post-process motion blur intensity increase
for cinematic slow motion without disrupting gameplay state.
Player->SetPlayRate(0.5f)UGameplayStatics::SetGlobalTimeDilation要在序列中实现慢动作效果,使用序列播放器的——这与无关,不会影响世界物理或其他游戏系统。结合后期处理的运动模糊强度增加,可实现不破坏游戏状态的镜头慢动作。
Player->SetPlayRate(0.5f)UGameplayStatics::SetGlobalTimeDilationMovie Render Queue
Movie Render Queue
cpp
// MovieRenderPipelineCore module. Classes:
// UMoviePipelineQueue — holds jobs
// UMoviePipelineExecutorJob — sequence + map + config per job
// UMoviePipelinePrimaryConfig — root settings container
// UMoviePipelineOutputSetting — output path, file name format, frame rate
// Output formats: UMoviePipelineImageSequenceOutput_PNG / _EXR, UMoviePipelineAppleProResOutput
// Render passes: UMoviePipelineDeferredPassBase (final color, world normal, base color, depth)
// Add passes to the PrimaryConfig to capture multiple AOVs per frame
UMoviePipelineQueue* Queue = NewObject<UMoviePipelineQueue>(this);
UMoviePipelineExecutorJob* Job =
Queue->AllocateNewJob(UMoviePipelineExecutorJob::StaticClass());
Job->Sequence = FSoftObjectPath(MySequence);
Job->Map = FSoftObjectPath(GetWorld());
Job->JobName = TEXT("MyRender");
Job->SetConfiguration(NewObject<UMoviePipelinePrimaryConfig>(Job));
// Add pass/output settings to Job->GetConfiguration() as needed.
// Execute the render (editor only — MovieRenderPipelineEditor module)
UMoviePipelineQueueEngineSubsystem* QueueSubsystem =
GEngine->GetEngineSubsystem<UMoviePipelineQueueEngineSubsystem>();
QueueSubsystem->RenderQueueWithExecutor(UMoviePipelineInProcessExecutor::StaticClass());
// For runtime/non-editor rendering, implement UMoviePipelineExecutorBase instead.cpp
// MovieRenderPipelineCore模块。相关类:
// UMoviePipelineQueue — 存储任务
// UMoviePipelineExecutorJob — 每个任务包含序列+地图+配置
// UMoviePipelinePrimaryConfig — 根设置容器
// UMoviePipelineOutputSetting — 输出路径、文件名格式、帧率
// 输出格式:UMoviePipelineImageSequenceOutput_PNG / _EXR, UMoviePipelineAppleProResOutput
// 渲染通道:UMoviePipelineDeferredPassBase(最终颜色、世界法线、基础颜色、深度)
// 向PrimaryConfig添加通道以捕获每帧的多个AOV
UMoviePipelineQueue* Queue = NewObject<UMoviePipelineQueue>(this);
UMoviePipelineExecutorJob* Job =
Queue->AllocateNewJob(UMoviePipelineExecutorJob::StaticClass());
Job->Sequence = FSoftObjectPath(MySequence);
Job->Map = FSoftObjectPath(GetWorld());
Job->JobName = TEXT("MyRender");
Job->SetConfiguration(NewObject<UMoviePipelinePrimaryConfig>(Job));
// 根据需要向Job->GetConfiguration()添加通道/输出设置。
// 执行渲染(仅编辑器——需要MovieRenderPipelineEditor模块)
UMoviePipelineQueueEngineSubsystem* QueueSubsystem =
GEngine->GetEngineSubsystem<UMoviePipelineQueueEngineSubsystem>();
QueueSubsystem->RenderQueueWithExecutor(UMoviePipelineInProcessExecutor::StaticClass());
// 对于运行时/非编辑器渲染,需自行实现UMoviePipelineExecutorBase。Common Mistakes
常见错误
Binding after Play: Overrides applied after miss frame 0.
Always before .
Play()SetBinding*Play()Multiplayer camera cuts: Camera cuts only affect the local client.
Use for server-driven sync.
SeqActor->SetReplicatePlayback(true)Camera not returning after cutscene: Sequencer does not auto-restore the player camera.
Subscribe to and call + re-enable input.
OnFinishedSetViewTargetWithBlendGC of spawned sequence actor: returns a raw pointer.
Store in a member to prevent garbage collection.
CreateLevelSequencePlayerOutActorUPROPERTY()Skipping mid-sequence: Call before
so actors return to their pre-sequence state.
SetCompletionModeOverride(ForceRestoreState)Stop()PIE timing: Avoid wall-clock assumptions; use frame numbers.
GetCurrentTime()Deprecated direct property: is deprecated since UE 5.4.
Use .
SeqActor->SequencePlayerSeqActor->GetSequencePlayer()Wrong player instance: Calling on a stale or mismatched
pointer (e.g., from a different in the level) produces no visible effect
or animates the wrong actors. Always retrieve the player from the specific
that owns the sequence you intend to drive.
Play()ULevelSequencePlayerALevelSequenceActorALevelSequenceActor播放后绑定:在之后应用的覆盖会错过第0帧。务必在之前调用。
Play()Play()SetBinding*多人游戏镜头切换:镜头切换仅影响本地客户端。使用实现服务器驱动的同步。
SeqActor->SetReplicatePlayback(true)过场后镜头未恢复:Sequencer不会自动恢复玩家镜头。订阅并调用 + 重新启用输入。
OnFinishedSetViewTargetWithBlend生成的序列Actor被垃圾回收:返回原始指针。将存储在成员中以防止被垃圾回收。
CreateLevelSequencePlayerOutActorUPROPERTY()中途跳过序列:在调用之前调用,使Actor恢复到序列前的状态。
Stop()SetCompletionModeOverride(ForceRestoreState)PIE时序问题:避免依赖挂钟时间;使用的帧编号。
GetCurrentTime()已弃用的直接属性:在UE 5.4及以上版本已被弃用。使用。
SeqActor->SequencePlayerSeqActor->GetSequencePlayer()错误的播放器实例:在过期或不匹配的指针上调用(例如来自关卡中另一个)会导致无可见效果或动画错误的Actor。务必从你要控制的序列所属的特定中获取播放器。
ULevelSequencePlayerPlay()ALevelSequenceActorALevelSequenceActorRelated Skills
相关技能
- — actor spawning and component setup for bound actors
ue-actor-component-architecture - — skeletal animation tracks, AnimMontage integration in Sequencer
ue-animation-system - — delegate patterns,
ue-cpp-foundations,UFUNCTIONUPROPERTY - — PlayerController camera restoration, GameMode flow
ue-gameplay-framework
- — 绑定Actor的生成与组件设置
ue-actor-component-architecture - — 骨骼动画轨道、AnimMontage与Sequencer的集成
ue-animation-system - — 委托模式、
ue-cpp-foundations、UFUNCTIONUPROPERTY - — PlayerController镜头恢复、GameMode流程
ue-gameplay-framework