Dependency problems in BP when using the few available events for setting them up. Expose extra initialization function from C++?

Objects often require a stage of setup before to set their own properties properly before communicating with other Objects. In Blueprint, the by default available events to set things up are quite limited. For example the ActorComponent only has BeginPlay to set things up and there is no way of knowing in what order a bunch of ActorComponents all fire their BeginPlay. If they require communication with eachother this leads to dependency problems.

Problem Example:
Both a created Widget and ActorComponent run their own setup function in BP on creation. During setup the widget communicates with the actor component to request data. The game crashes because the ActorComponent was last to perform its setup (both performed setup on BeginPlay, but in any order) and because of that dit not get any chance to set the requested property yet.

The Questions…:

  • What is a clean solution to solve mentioned problem without adding validity checks everywhere, that scales well with large frameworks?
  • Would exposing an initalization event from C++ to BP be a fix, to setup properties early, or is this problem unavoidable at later moments?

Possible Solution:
Exposing a C++ Initialize function to Blueprint before BeginPlay so Objects can setup their own custom properties before requesting data from other classes (Do that later on BeginPlay?).

In C++ there are many more events accessible at different stages of the classes their creation and some are exposable to BluePrint.

I’ve read quite a few questions already on the topic and it seems most BP users don’t know how events are ordered when they spawn actors, so for information purpose here I dump the relevant event execution order for my case (spawning or placing actors in editor) as I found them in C++, without the ifs and elses… higher indentation means called by the function above it with lower indentation.

UWorld::SpawnActor
-AActor::PostSpawnInitialize
--AActor::RegisterAllComponents
---AActor::PreRegisterAllComponents
---UActorComponent::RegisterComponent
----UActorComponent::RegisterComponentWithWorld
-----UActorComponent::OnComponentCreated
-----UActorComponent::InitializeComponent
-----UActorComponent::BeginPlay
---AActor::PostRegisterAllComponents
--AActor::PostActorCreated
--AActor::FinishSpawning
---AActor::ExecuteConstruction
----AActor::OnConstruction
---AActor::PostActorConstruction
----AActor::PreInitializeComponents
----APawn::PreInitializeComponents
----AActor::InitializeComponents
-----UActorComponent::InitializeComponent
----AActor::PostInitializeComponents
----APawn::PostInitializeComponents
-----AController::Possess				
----AActor::DispatchBeginPlay
-----AActor::BeginPlay
------UActorComponent::BeginPlay
-------UActorComponent::ReceiveBeginPlay
------AActor::ReceiveBeginPlay

For the Actor and the ActorComponent the following functions look OK ish to override for exposing to BP and setup their custom stuff, but it isn’t… perfect… And what about modifying the Object class itself?

AActor::PostInitializeComponents
UActorComponent::InitializeComponent

I’ve spent three days thinking about how to get this perfected and clean, for my own framework. Just what am I missing?

Solved this specific issue by always using getters (GetOwningPlayerPawn, GetComponentByClass) to get the ActorComponents in the functions where they were required, instead of setting the references OnBeginPlay which was often too late. It got benefits but a bit unnessecary for classes where I just want to set a reference once and not at any time later. Best practices?