在https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Actors/ActorLifecycle 官方的编程文档中,UE4官方给出了有关Actor生命周期的宝贵资料.
Actor生命周期概述图
这里我就跟着资料追着源码剖解一遍游戏运行时产生Actor的函数-----------------SpawnActor和SpawnActorDeferred的产生Actor调用各种函数的流程
SpawnActor产生并初始化Actor的流程
World.h
在UE4中我们一般调用来自于 World.h 的各种SpawnActor<T>(....),如下面的
template< class T >
T* SpawnActor( UClass* Class, FVector const& Location, FRotator const& Rotation, const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters() )
{
return CastChecked<T>(SpawnActor(Class, &Location, &Rotation, SpawnParameters),ECastCheckedType::NullAllowed);
}
SpawnActor<T>各种模板函数的SpawnActor来源于LevelActor.cpp,所以我们来到LevelActor.cpp。
LevelActor.cpp
上面在 Wolrd.h 的各种 SpawnActor 的模板函数都来源于LevelActor.cpp的SpawnActor函数,贴出小部分代码:
在LevelActor.cpp 299 行
AActor* UWorld::SpawnActor( UClass* Class, FTransform const* UserTransformPtr, const FActorSpawnParameters& SpawnParameters )
{
SCOPE_CYCLE_COUNTER(STAT_SpawnActorTime);
SCOPE_TIME_GUARD_NAMED_MS(TEXT("SpawnActor Of Type"), Class->GetFName(), 2);
check( CurrentLevel );
check(GIsEditor || (CurrentLevel == PersistentLevel));
// Make sure this class is spawnable.
if( !Class )
{
UE_LOG(LogSpawn, Warning, TEXT("SpawnActor failed because no class was specified") );
return NULL;
}
#if ENABLE_SPAWNACTORTIMER
FScopedSpawnActorTimer SpawnTimer(Class->GetFName(), SpawnParameters.bDeferConstruction ? ESpawnActorTimingType::SpawnActorDeferred : ESpawnActorTimingType::SpawnActorNonDeferred);
#endif
往下看来到 LevelActor.cpp 432 行, 可以看到我们的Actor创建其实也是通过NewObject
AActor* const Actor = NewObject<AActor>(LevelToSpawnIn, Class, NewActorName, SpawnParameters.ObjectFlags, Template);
往下看到 LevelActor.cpp 465 行,看到对应Actor生命周期图----Actor的PostSpawnInitialize函数执行
Actor->PostSpawnInitialize(UserTransform, SpawnParameters.Owner, SpawnParameters.Instigator, SpawnParameters.IsRemoteOwned(), SpawnParameters.bNoFail, SpawnParameters.bDeferConstruction);
下面追寻到 Actor.cpp 中去。
Actor.cpp
上面说到Actor的PostSpawnInitialize函数执行,PostSpawnInitialize在 Actor.cpp 的 2816 行
看下面函数小部分源码
void AActor::PostSpawnInitialize(FTransform const& UserSpawnTransform, AActor* InOwner, APawn* InInstigator, bool bRemoteOwned, bool bNoFail, bool bDeferConstruction)
{
// General flow here is like so
// - Actor sets up the basics.
// - Actor gets PreInitializeComponents()
// - Actor constructs itself, after which its components should be fully assembled
// - Actor components get OnComponentCreated
// - Actor components get InitializeComponent
// - Actor gets PostInitializeComponents() once everything is set up
//
// This should be the same sequence for deferred or nondeferred spawning.
// It's not safe to call UWorld accessor functions till the world info has been spawned.
UWorld* const World = GetWorld();
bool const bActorsInitialized = World && World->AreActorsInitialized();
CreationTime = (World ? World->GetTimeSeconds() : 0.f);
// Set network role.
check(Role == ROLE_Authority);
ExchangeNetRoles(bRemoteOwned);
USceneComponent* const SceneRootComponent = FixupNativeActorComponents(this);
往下面看,来到 2910 行,看见 PostActorCreated函数
// Send messages. We've fully spawned
PostActorCreated();
看下PostActorCreated在 类Actor的声明和定义:
/**
* Called when an actor is done spawning into the world (from UWorld::SpawnActor).
* For actors with a root component, the location and rotation will have already been set.
* Takes place after any construction scripts have been called
*/
void AActor::PostActorCreated()
{
// nothing at the moment
}
protected 的virtual 函数,这个是我们在AActor类构造函数之后的第一个可以Override的
忘下面看,然后我们到 2914行 的 FinishSpawning 函数执行,比较注意的是这里有个if (!bDeferConstruction) 判断,我们用
SpawnActor<T>时,bDeferConstruction = false,因此可以执行FinishSpawning
// Executes native and BP construction scripts.
// After this, we can assume all components are created and assembled.
if (!bDeferConstruction)
{
FinishSpawning(UserSpawnTransform, true);
}
来到 FinishSpawning 函数的执行代码,贴出一小部分
void AActor::FinishSpawning(const FTransform& UserTransform, bool bIsDefaultTransform, const FComponentInstanceDataCache* InstanceDataCache)
{
#if ENABLE_SPAWNACTORTIMER
FScopedSpawnActorTimer SpawnTimer(GetClass()->GetFName(), ESpawnActorTimingType::FinishSpawning);
SpawnTimer.SetActorName(GetFName());
#endif
if (ensure(!bHasFinishedSpawning))
{
bHasFinishedSpawning = true;
来到 2970行,看到ExecuteConstruction函数的执行
ExecuteConstruction(FinalRootComponentTransform, nullptr, InstanceDataCache, bIsDefaultTransform);
ExecuteConstruction是声明在AActor的函数,但是定义 在ActorConstruction.cpp函数,下面我们到ActorConstruction.cpp去
ActorConstruction.cpp
来到 ActorConstruction.cpp的647行,看到ExecuteConstruction函数,贴出小部分代码
bool AActor::ExecuteConstruction(const FTransform& Transform, const FRotationConversionCache* TransformRotationCache, const FComponentInstanceDataCache* InstanceDataCache, bool bIsDefaultTransform)
{
check(!IsPendingKill());
check(!HasAnyFlags(RF_BeginDestroyed|RF_FinishDestroyed));
// ensure that any existing native root component gets this new transform
// we can skip this in the default case as the given transform will be the root component's transform
if (RootComponent && !bIsDefaultTransform)
{
来到839行,看到OnConstruction执行
// Now run virtual notification
OnConstruction(Transform);
OnConstruction 是声明在 AActor.h 定的 protected 的 virtual 函数, 这个接口我们可以考虑在AActor的子类进行override。
virtual void OnConstruction(const FTransform& Transform) {}
然后再次回到AActor.cpp 的 2974行,看到PostActorConstruction函数的执行
AActor.cpp
AActor.cpp 的 2974行
PostActorConstruction();
PostActorConstruction函数代码在AActor.cpp的2979行开始,贴出小部分代码:
void AActor::PostActorConstruction()
{
UWorld* const World = GetWorld();
bool const bActorsInitialized = World && World->AreActorsInitialized();
if (bActorsInitialized)
{
PreInitializeComponents();
}
来到 2986行 的,看到 PreInitializeComponents函数的执行
PreInitializeComponents();
PreInitializeComponents 是声明在 AActor.h, 定义在 AActor.cpp 的 protected virtual 函数
virtual void PreInitializeComponents();
void AActor::PreInitializeComponents()
{
if (AutoReceiveInput != EAutoReceiveInput::Disabled)
{
const int32 PlayerIndex = int32(AutoReceiveInput.GetValue()) - 1;
APlayerController* PC = UGameplayStatics::GetPlayerController(this, PlayerIndex);
if (PC)
{
EnableInput(PC);
}
else
{
GetWorld()->PersistentLevel->RegisterActorForAutoReceiveInput(this, PlayerIndex);
}
}
}
下面来到 2995行,看到 InitializeComponents 的执行
// Call InitializeComponent on components
InitializeComponents();
看InitializeComponents函数声明
/** Iterate over components array and call InitializeComponent */
void InitializeComponents();
很可惜的一点是 InitializeComponents 并不是protected virtual 函数,因此无法在 AActor.h 子类中Override
往下面看,来到 3047 行,看到PostInitializeComponents函数的执行, PostInitializeComponents是AActor的protected virtual 函数,可以考虑在 AActor 子类中Override
/** Allow actors to initialize themselves on the C++ side */
virtual void PostInitializeComponents();
void AActor::PostInitializeComponents()
{
if( !IsPendingKill() )
{
bActorInitialized = true;
FNavigationSystem::OnActorRegistered(*this);
UpdateAllReplicatedComponents();
}
}
继续往下面走,看到DispatchBeginPlay函数的执行
DispatchBeginPlay();
void AActor::DispatchBeginPlay()
{
UWorld* World = (!HasActorBegunPlay() && !IsPendingKill() ? GetWorld() : nullptr);
if (World)
{
const uint32 CurrentCallDepth = BeginPlayCallDepth++;
BeginPlay();
ensure(BeginPlayCallDepth - 1 == CurrentCallDepth);
BeginPlayCallDepth = CurrentCallDepth;
if (bActorWantsDestroyDuringBeginPlay)
{
// Pass true for bNetForce as either it doesn't matter or it was true the first time to even
// get to the point we set bActorWantsDestroyDuringBeginPlay to true
World->DestroyActor(this, true);
}
}
}
我们最终可以看到 BeginPlay 函数 的,BeginPlay函数也是AActor的protected virtual函数,可以考虑在AAcctor子类override
/** Overridable native event for when play begins for this actor. */
virtual void BeginPlay();
void AActor::BeginPlay()
{
ensureMsgf(ActorHasBegunPlay == EActorBeginPlayState::HasNotBegunPlay, TEXT("BeginPlay was called on actor %s which was in state %d"), *GetPathName(), (int32)ActorHasBegunPlay);
SetLifeSpan( InitialLifeSpan );
RegisterAllActorTickFunctions(true, false); // Components are done below.
TInlineComponentArray<UActorComponent*> Components;
GetComponents(Components);
ActorHasBegunPlay = EActorBeginPlayState::BeginningPlay;
for (UActorComponent* Component : Components)
{
// bHasBegunPlay will be true for the component if the component was renamed and moved to a new outer during initialization
if (Component->IsRegistered() && !Component->HasBegunPlay())
{
Component->RegisterAllComponentTickFunctions(true);
Component->BeginPlay();
ensureMsgf(Component->HasBegunPlay(), TEXT("Failed to route BeginPlay (%s)"), *Component->GetFullName());
}
else
{
// When an Actor begins play we expect only the not bAutoRegister false components to not be registered
//check(!Component->bAutoRegister);
}
}
ReceiveBeginPlay();
ActorHasBegunPlay = EActorBeginPlayState::HasBegunPlay;
}
好吧,整天SpawnActor函数的产生AActor,AActor初始化的流程就差不多走了大概,下面总结下SpawnActor和Actor的初始化流程
SpawnActor产生并初始化Actor的流程图
棕色标注的函数的AActor可改写的,我们可以在AActor的子类中override的。
得注意一点的我,我在追源码并发现“OnActorSpawn”这个并不是函数,而是一个委托,用来通知AActor已经Spawn。在PostSpawnInitialize函数执行之后,位于LevelActor.cpp的 476 行
// Broadcast notification of spawn
OnActorSpawned.Broadcast(Actor);
这个委托是UWorld的委托, 定义在Wolrd.h的1063行
DECLARE_MULTICAST_DELEGATE_OneParam(FOnActorSpawned, AActor*);
/** a delegate that broadcasts a notification whenever an actor is spawned */
FOnActorSpawned OnActorSpawned;
不是函数的话我就不添加到流程图了。
其实在AActor.h就有类似的说明了“AActor初始化顺序”注释
class ENGINE_API AActor : public UObject
{
/**
* The functions of interest to initialization order for an Actor is roughly as follows:
* PostLoad/PostActorCreated - Do any setup of the actor required for construction. PostLoad for serialized actors, PostActorCreated for spawned.
* AActor::OnConstruction - The construction of the actor, this is where Blueprint actors have their components created and blueprint variables are initialized
* AActor::PreInitializeComponents - Called before InitializeComponent is called on the actor's components
* UActorComponent::InitializeComponent - Each component in the actor's components array gets an initialize call (if bWantsInitializeComponent is true for that component)
* AActor::PostInitializeComponents - Called after the actor's components have been initialized
* AActor::BeginPlay - Called when the level is started
*/
demo演示
UCLASS()
class MYPROJECT4_API ATestActor : public AActor
{
GENERATED_BODY()
ATestActor();
protected:
// Called when the game starts or when spawned
virtual void PostActorCreated() override;
virtual void OnConstruction(const FTransform& Transform) override;
virtual void PreInitializeComponents() override;
virtual void PostInitializeComponents() override;
virtual void BeginPlay() override;
}
ATestActor::ATestActor()
{
UE_LOG(LogTemp, Error, TEXT("ATestActor Construction"));
}
void ATestActor::PostActorCreated()
{
Super::PostActorCreated();
UE_LOG(LogTemp, Error, TEXT("ATestActor::PostActorCreated"));
}
void ATestActor::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
UE_LOG(LogTemp, Error, TEXT("ATestActor::OnConstruction"));
}
void ATestActor::PreInitializeComponents()
{
Super::PreInitializeComponents();
UE_LOG(LogTemp, Error, TEXT("ATestActor::PreInitializeComponents"));
}
void ATestActor::PostInitializeComponents()
{
Super::PostInitializeComponents();
UE_LOG(LogTemp, Error, TEXT("ATestActor::PostInitializeComponents"));
}
void ATestActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Error, TEXT("ATestActor::BeginPlay"));
}
SpawnActorDeferred产生并初始化Actor的流程
World.h
在UE4中我们一般调用来自于 World.h 的各种SpawnActorDeferred<T>(....), 如下面的
template< class T >
T* SpawnActorDeferred(
UClass* Class,
FTransform const& Transform,
AActor* Owner = nullptr,
APawn* Instigator = nullptr,
ESpawnActorCollisionHandlingMethod CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined
)
{
if( Owner )
{
check(this==Owner->GetWorld());
}
FActorSpawnParameters SpawnInfo;
SpawnInfo.SpawnCollisionHandlingOverride = CollisionHandlingOverride;
SpawnInfo.Owner = Owner;
SpawnInfo.Instigator = Instigator;
SpawnInfo.bDeferConstruction = true;
return (Class != nullptr) ? Cast<T>(SpawnActor(Class, &Transform, SpawnInfo)) : nullptr;
}
AActor.cpp
SpawnActorDeferred前面流程和SpawnActor是差不多的(PostActorCreated函数执行前面的流程包括PostActorCreated)
有再次来到AActor.cpp 的 2914行
if (!bDeferConstruction)
{
FinishSpawning(UserSpawnTransform, true);
}
这个bDeferConstruction来自于FActorSpawnParameters结构体的bDeferConstruction
Actor->PostSpawnInitialize(UserTransform, SpawnParameters.Owner, SpawnParameters.Instigator, SpawnParameters.IsRemoteOwned(), SpawnParameters.bNoFail, SpawnParameters.bDeferConstruction);
看SpawnActorDeferredActor<T> 函数的
SpawnInfo.bDeferConstruction = true;
因此SpawnActorDeferred无法执行FinishSpawning(UserSpawnTransform, true);
SpawnActorDeferred产生并初始化Actor的流程图
demo演示
代码上上面的一样
void AMyProject4Character::SpawnTestActor()
{
ATestActor* testActor = GetWorld()->SpawnActorDeferred<ATestActor>(ATestActor::StaticClass(), GetTransform());
UE_LOG(LogTemp, Error, TEXT("xxxxxxxxxxxxxxxxxxxxxxxx"));
}
上面这么多protected virtual 函数就执行了PostActorCreated,BeginPlay这个在业务逻辑中常用的初始化函数也不执行。
参考资料
【1】https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Actors/ActorLifecycle