Beginplay在关卡被加载的时候执行且仅运行时被调用。那么C++和蓝图的Beginplay函数执行顺序如何呢?
太长不看版本
先说结论:实际上取决于C++在Beginplay函数体中调用父类Beginplay方法的时机。有且仅有调用父类BeginPlay之前的逻辑会在蓝图BeginPlay之前执行。
因为蓝图的BeginPlay是在AActor::BeginPlay()方法中被调用的
举个栗子
来看一个例子
// Called when the game starts or when spawned
void ABeginplayOrderTest::BeginPlay()
{
UE_LOG(LogTemp, Warning, TEXT("CPP Before BeginPlay"));
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("CPP After BeginPlay"));
}
执行结果:
源码分析
继承于Actor的对象在调用Super::BeginPlay以后会调到AActor::BeginPlay()
而这个函数中调到了一个BlueprintImplementableEvent的方法ReceiveBeginPlay();
它实际上就是蓝图的Event BeginPlay
ReceiveBeginPlay();
方法声明:
//AActor.h
/** Event when play begins for this actor. */
UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "BeginPlay"))
void ReceiveBeginPlay();
完整函数体:
// AActor.cpp
void AActor::BeginPlay()
{
TRACE_OBJECT_EVENT(this, BeginPlay);
ensureMsgf(ActorHasBegunPlay == EActorBeginPlayState::BeginningPlay, 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);
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);
}
}
if (GetAutoDestroyWhenFinished())
{
if (UWorld* MyWorld = GetWorld())
{
if (UAutoDestroySubsystem* AutoDestroySys = MyWorld->GetSubsystem<UAutoDestroySubsystem>())
{
AutoDestroySys->RegisterActor(this);
}
}
}
ReceiveBeginPlay();
ActorHasBegunPlay = EActorBeginPlayState::HasBegunPlay;
}