【UE】蓝图和C++ Beginplay执行顺序

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

猜你喜欢

转载自blog.csdn.net/weixin_44559752/article/details/127177576
今日推荐