[UE学习笔记][基于源码] 理解 Gameplay
基于 UE 5.7 引擎源码(
Engine/Source/Runtime/Engine/Private/)
完整生命周期
UActorComponent AActor AWorldSettings AGameStateBase AGameModeBase ULevel UWorld GEngine UActorComponent AActor AWorldSettings AGameStateBase AGameModeBase ULevel UWorld GEngine CDO 默认值整体复制到实例 Details Panel 中的属性覆盖值(delta)写入实例 子对象/组件引用重定向到本实例 loop [关卡中每个 AActor] 此后属性已就位,组件引用已解析 注册所有组件到世界 ⚠️ 仅 PIE / 非 Cook 环境(bRerunConstructionScript=true) SCS 执行,创建蓝图组件 loop [所有 Level-placed AActor] 最早的 GameMode 初始化点 Phase 1 loop [所有 AActor] Phase 2 bActorInitialized = true loop [所有 AActor] Phase 3 loop [所有 AActor(非 ChildActor)] 跳过,BeginPlay 由 NotifyBeginPlay 统一触发 alt [HasBegunPlay() == true(流送关卡)] [HasBegunPlay() == false(初始加载)] loop [所有 Level] loop [所有 AActor(按 Actors 数组顺序)] ── 唯一的一帧 ── 默认 TG_PrePhysics;物理在 StartPhysics~EndPhysics 之间模拟 loop [TG_PrePhysics → StartPhysics → DuringPhysics → EndPhysics → PostPhysics → PostUpdateWork → LastDemotable] 无 Actor 绑定的 Latent Action SetTimer / FTimerHandle 回调在此触发 ── 关闭 ── loop [所有 AActor] LoadMap() / LoadPackage() 1 NewObject(CDO as template) 2 UObject::Serialize() 3 PostLoadSubobjects() 4 PostLoad() 5 InitWorld() 6 InitializeActorsForPlay(URL) 7 UpdateWorldComponents(bRerunCS) 8 RerunConstructionScripts() 9 ExecuteConstruction() 10 📢 UserConstructionScript() 11 🔓 OnConstruction(Transform) 12 🔓 InitGame(Map, Options) 13 RouteActorInitialize() 14 🔓 PreInitializeComponents() 15 InitializeComponents() 16 🔓 InitializeComponent() 17 🔓 PostInitializeComponents() 18 DispatchBeginPlay(bFromLevelStreaming=true) 19 BeginPlay() 20 🔓 OnWorldBeginPlay [WorldSubsystem] 21 🔓 StartPlay() 22 🔓 HandleBeginPlay() 23 🔓 NotifyBeginPlay() 24 📢 OnWorldPreBeginPlay.Broadcast() 25 DispatchBeginPlay() 26 SetBegunPlay(true) 27 (return) 28 📢 OnWorldBeginPlay.Broadcast() 29 Tick(DeltaTime) 30 FActorTickFunction::ExecuteTick() 31 FActorComponentTickFunction::ExecuteTick() 32 LatentActionManager.ProcessLatentActions(nullptr) 33 TimerManager.Tick() 34 EndPlay(Quit) 35 BeginTearingDown() 36 RouteEndPlay(Quit) 37 🔓 OnWorldEndPlay [WorldSubsystem] 38 SetBegunPlay(false) 39 CleanupWorld() 40
图注:
- 🔓 该函数为
virtual,可在 C++ 子类中override- 📢 触发蓝图事件或委托广播,可在蓝图中响应
RouteEndPlay()、DispatchBeginPlay()、InitializeComponents()无标记,为非虚引擎内部调度函数- Phase 3 标注"跳过"是初始加载最容易误解的地方------BeginPlay 由后续
NotifyBeginPlay统一触发,而非RouteActorInitialize- Component 的
ReceiveBeginPlay先于 Actor 的ReceiveBeginPlay(蓝图 Event BeginPlay)- EndPlay 顺序与 BeginPlay 相反:Actor 蓝图先收到通知,Component 后收到
DispatchBeginPlay & RouteEndPlay
DispatchBeginPlay
UActorComponent AActor UActorComponent AActor bHasBegunPlay = true loop [所有已注册 Component] ActorHasBegunPlay = EActorBeginPlayState::HasBegunPlay DispatchBeginPlay() 1 🔓 BeginPlay() 2 RegisterAllActorTickFunctions() 3 RegisterAllComponentTickFunctions() 4 🔓 BeginPlay() 5 📢 ReceiveBeginPlay 6 📢 ReceiveBeginPlay 7
RouteEndPlay
UActorComponent AActor UActorComponent AActor bHasBegunPlay = false loop [所有 Component(已 BegunPlay)] RouteEndPlay(Reason) 1 🔓 EndPlay(Reason) 2 📢 ReceiveEndPlay(Reason) 3 📢 OnEndPlay.Broadcast(Reason) 4 🔓 EndPlay(Reason) 5 📢 ReceiveEndPlay(Reason) 6 UninitializeComponents() 7
Tick 详细流程
FActorTickFunction::ExecuteTick
AActor AActor 该 Actor 绑定的 Delay 等 Latent Action 在此恢复 FActorTickFunction::ExecuteTick() 1 🔓 Tick(DeltaSeconds) 2 📢 ReceiveTick(DeltaSeconds) 3 LatentActionManager.ProcessLatentActions(this) 4
FActorComponentTickFunction::ExecuteTick
UActorComponent UActorComponent FActorComponentTickFunction::ExecuteTick() 1 🔓 TickComponent(DeltaSeconds) 2 📢 ReceiveTickComponent(DeltaSeconds) 3
运行时 Spawn
UWorld::SpawnActor
UActorComponent AActor UWorld 调用方 UActorComponent AActor UWorld 调用方 构造函数执行,CDO 默认属性复制到实例 设置 Transform 到 RootComponent 有原生根组件时注册,纯蓝图类可能延迟 FinishSpawning 不在此处调用,初始化未完成 alt [bDeferConstruction == false] [bDeferConstruction == true] SpawnActor(Class, Transform, Params) 1 NewObject(CDO as template) 2 PostSpawnInitialize(bDeferConstruction) 3 FixupNativeActorComponents() 4 🔓 OnComponentCreated() [原生组件] 5 RegisterAllComponents() 6 🔓 PostActorCreated() 7 FinishSpawning(Transform) 8 返回 Actor 指针(BeginPlay 已执行完) 9 返回 Actor 指针(未完成初始化!) 10
SpawnActorDeferred
AActor UWorld 调用方 AActor UWorld 调用方 ── 窗口期:Construction Script / BeginPlay 均可读到以下赋值 ── SpawnActorDeferred(Class, Transform) 1 SpawnActor(bDeferConstruction=true) 2 返回 Actor 指针(未完成初始化!) 3 MyActor->>Prop = Value 4 UGameplayStatics::FinishSpawningActor(Actor, Transform) 5 FinishSpawning(Transform) 6 返回完成初始化的 Actor 指针 7
蓝图 Spawn Actor from Class
AActor UWorld UGameplayStatics 蓝图节点 AActor UWorld UGameplayStatics 蓝图节点 ── 窗口期:Expose on Spawn 引脚赋值 ── loop [每个 Expose on Spawn 引脚] [节点编译后展开为以下三段] 1 BeginDeferredActorSpawnFromClass() 2 SpawnActorDeferred() 3 (return) 4 返回 Actor 指针(未完成初始化!) 5 Actor->>ExposedProp = PinValue 6 FinishSpawningActor(Actor, Transform) 7 FinishSpawning(Transform) 8 返回完成初始化的 Actor 指针 9
FinishSpawning
UActorComponent AActor 调用方 UActorComponent AActor 调用方 SCS 执行,创建蓝图组件 bActorInitialized = true BeginPlay 等待 NotifyBeginPlay 统一触发 alt [World.HasBegunPlay() == true] [World.HasBegunPlay() == false] FinishSpawning(Transform) 1 ExecuteConstruction(Transform) 2 📢 UserConstructionScript() 3 🔓 OnConstruction(Transform) 4 PostActorConstruction() 5 🔓 PreInitializeComponents() 6 InitializeComponents() 7 🔓 InitializeComponent() [bWantsInitializeComponent=true 时] 8 🔓 PostInitializeComponents() 9 DispatchBeginPlay() 10 FinishSpawning 返回 11
图注:
SpawnActor返回时 BeginPlay 已执行完,调用方拿到的是完全初始化的指针SpawnActorDeferred返回时 初始化未完成 ,必须调用FinishSpawningActor才能完成- 蓝图节点内部就是 Deferred 模式,
Expose on Spawn引脚在窗口期自动赋值
运行时销毁
UWorld::DestroyActor
UActorComponent ULevel UWorld AActor 调用方 UActorComponent ULevel UWorld AActor 调用方 IsPendingKillPending → 直接返回 true(幂等) IsActorBeginningPlay → 推迟到 BeginPlay 结束后执行 标记为待 GC,下次 GC 时释放内存 🔓 Destroy() 1 DestroyActor(this) 2 📢 OnActorDestroyed.Broadcast() 3 🔓 Destroyed() 4 RouteEndPlay(EEndPlayReason::Destroyed) 5 📢 ReceiveDestroyed() 6 📢 OnDestroyed.Broadcast() 7 DetachAllSceneComponents(子 Actor 解绑) 8 RemoveActor() 9 📢 OnActorRemovedFromWorld.Broadcast() 10 UnregisterAllComponents() 11 MarkAsGarbage() 12 (return) 13
源码速查
| 函数签名 | 源码位置 |
|---|---|
UWorld::InitializeActorsForPlay() |
Source/Runtime/Engine/Private/World.cpp:5842 |
UWorld::BeginPlay() |
Source/Runtime/Engine/Private/World.cpp:6044 |
UWorld::EndPlay() |
Source/Runtime/Engine/Private/World.cpp:6080 |
UWorld::SpawnActor() |
Source/Runtime/Engine/Private/LevelActor.cpp:455 |
ULevel::RouteActorInitialize() |
Source/Runtime/Engine/Private/Level.cpp:3817 |
AGameModeBase::StartPlay() |
Source/Runtime/Engine/Private/GameModeBase.cpp:204 |
AGameStateBase::HandleBeginPlay() |
Source/Runtime/Engine/Private/GameStateBase.cpp:205 |
AWorldSettings::NotifyBeginPlay() |
Source/Runtime/Engine/Private/WorldSettings.cpp:353 |
AActor::PostSpawnInitialize() |
Source/Runtime/Engine/Private/Actor.cpp:4249 |
AActor::PostActorCreated() |
Source/Runtime/Engine/Private/Actor.cpp:2094 |
AActor::RegisterAllComponents() |
Source/Runtime/Engine/Private/Actor.cpp:5941 |
AActor::PreInitializeComponents() |
Source/Runtime/Engine/Private/Actor.cpp:6556 |
AActor::InitializeComponents() |
Source/Runtime/Engine/Private/Actor.cpp:6325 |
AActor::PostInitializeComponents() |
Source/Runtime/Engine/Private/Actor.cpp:6544 |
AActor::DispatchBeginPlay() |
Source/Runtime/Engine/Private/Actor.cpp:4690 |
AActor::BeginPlay() |
Source/Runtime/Engine/Private/Actor.cpp:4753 |
AActor::RouteEndPlay() |
Source/Runtime/Engine/Private/Actor.cpp:3194 |
AActor::EndPlay() |
Source/Runtime/Engine/Private/Actor.cpp:3232 |
AActor::FinishSpawning() |
Source/Runtime/Engine/Private/Actor.cpp:4347 |
AActor::PostActorConstruction() |
Source/Runtime/Engine/Private/Actor.cpp:4403 |
AActor::RerunConstructionScripts() |
Source/Runtime/Engine/Private/ActorConstruction.cpp:252 |
AActor::ExecuteConstruction() |
Source/Runtime/Engine/Private/ActorConstruction.cpp:816 |
UActorComponent::OnComponentCreated() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:2155 |
UActorComponent::InitializeComponent() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:1589 |
UActorComponent::BeginPlay() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:1609 |
UActorComponent::EndPlay() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:1625 |
UGameplayStatics::BeginDeferredActorSpawnFromClass() |
Source/Runtime/Engine/Private/GameplayStatics.cpp:856 |
UGameplayStatics::FinishSpawningActor() |
Source/Runtime/Engine/Private/GameplayStatics.cpp:891 |
UWorld::Tick() |
Source/Runtime/Engine/Private/LevelTick.cpp:1477 |
FActorTickFunction::ExecuteTick() |
Source/Runtime/Engine/Private/Actor.cpp:370 |
AActor::Tick() |
Source/Runtime/Engine/Private/Actor.cpp:1971 |
FActorComponentTickFunction::ExecuteTick() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:1651 |
UActorComponent::TickComponent() |
Source/Runtime/Engine/Private/Components/ActorComponent.cpp:1838 |
EEndPlayReason (enum) |
Source/Runtime/Engine/Classes/Engine/EngineTypes.h:3428 |
AActor::Destroy() |
Source/Runtime/Engine/Private/Actor.cpp:5288 |
UWorld::DestroyActor() |
Source/Runtime/Engine/Private/LevelActor.cpp:838 |
AActor::Destroyed() |
Source/Runtime/Engine/Private/Actor.cpp:3284 |