你的浏览器不支持canvas

让我们携手共创奇迹!

UE Beginplay

Date: Author: LBD

本文章采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。转载请注明来自WindCrazy

这是一篇关于UE中蓝图Beginplay和C++中Beginplay

官方文档参考:Actor Lifecycle

Beginplay

One C++ Constructor > Corresponding BP Constructors > Repeat / One C++ Begin Play > Corresponding BP Begin Play

蓝图的BeginPlay是在AActor::BeginPlay()方法中被调用的

void AXXX::BeginPlay()
{
	UE_LOG(LogTest, Warning, TEXT("CPP 1 Begin"));
	Super::BeginPlay();
    UE_LOG(LogTest, Warning, TEXT("CPP 2 Begin"));
}

那么会看到

LogTest: Warning: CPP 1 Begin
LogBlueprintUserMessages: [BP_XXX_0] Blueprint Beginplay
LogTest: Warning: CPP 2 Begin

继承于Actor的对象在调用Super::BeginPlay以后会调到AActor::BeginPlay()

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;
}

其中倒数第二行调用到了BlueprintImplementableEvent的方法ReceiveBeginPlay(),这个就是蓝图里的Beginplay

protected:
	/** Event when play begins for this actor. */
	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "BeginPlay"))
	void ReceiveBeginPlay();

另外在调用此函数前遍历了此Actor的组件,因此组件的Beginplay会更早

void UActorComponent::BeginPlay()
{
	TRACE_OBJECT_EVENT(this, BeginPlay);

	check(bRegistered);
	check(!bHasBegunPlay);
	checkSlow(bTickFunctionsRegistered); // If this fails, someone called BeginPlay() without first calling RegisterAllComponentTickFunctions().

    //CLASS_CompiledFromBlueprint:表明该类是从蓝图创建的
    //CLASS_Native:Class is a native class - native interfaces will have CLASS_Native set, but not RF_MarkAsNative   与反射相关见下方 UE 反射实现分析 链接
	if (GetClass()->HasAnyClassFlags(CLASS_CompiledFromBlueprint) || !GetClass()->HasAnyClassFlags(CLASS_Native))
	{
		ReceiveBeginPlay();
	}

	bHasBegunPlay = true;
}
/** 
	 * Blueprint implementable event for when the component is beginning play, called before its owning actor's BeginPlay
	 * or when the component is dynamically created if the Actor has already BegunPlay. 
	 */
	UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "Begin Play"))
	void ReceiveBeginPlay();

参考:C++ for Blueprints

UE 反射实现分析


对于本文内容有问题或建议的小伙伴,欢迎提出问题