(UE4 4.20 ) UE4的Actor生命周期(1) 之 SpawnActor , SpawnActorDeferred 产生 Actor 和 AActor 初始化的执行流程

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值