Say I have created BaseActor in C++ and then create a BP class name BaseActorBP which inherit from this C++ BaseActor. How can I defer BeginPlay execution of BaseActorBP until the time I deemed is right (could be a few seconds late)?
BeginPlay is called by the engine, so you can’t. You can create your own event (I would just create a BlueprintNativeEvent on your C++ BaseActor) and call that when ever you deem it’s ready to call.
Of course I can create my event, it is just that many initialization is already done in BeginPlay and people are all very familiar with it.
I think it is possibe by hacking around (eg in C++, do not call Super::BeginPlay) and then there is this function ‘AActor:: DispatchBeginPlay’.
I can try this myself, but I am asking this just incase if anyone else has succesfully done this.
Problem is your trying to change the timing of a fundamental method in the actor lifecycle:
That’s why I think you’d have better luck not touching that and just creating your own. You could always add an assert, or on screen warning as the default implementation of your event to remind users to overload it.
This is from AActor.cpp (PostConstruction)
if (!IsPendingKill())
{
PostInitializeComponents();
if (!IsPendingKill())
{
if (!bActorInitialized)
{
UE_LOG(LogActor, Fatal, TEXT("%s failed to route PostInitializeComponents. Please call Super::PostInitializeComponents() in your <className>::PostInitializeComponents() function. "), *GetFullName());
}
bool bRunBeginPlay = !bDeferBeginPlayAndUpdateOverlaps && (BeginPlayCallDepth > 0 || World->HasBegunPlay());
if (bRunBeginPlay)
{
if (AActor* ParentActor = GetParentActor())
{
// Child Actors cannot run begin play until their parent has run
bRunBeginPlay = (ParentActor->HasActorBegunPlay() || ParentActor->IsActorBeginningPlay());
}
}
if (bRunBeginPlay)
{
SCOPE_CYCLE_COUNTER(STAT_ActorBeginPlay);
DispatchBeginPlay();
}
}
From a glance, you can set bDeferBeginPlayAndUpdateOverlaps to false in the Actor ctor and then later on, can call DispatchBeginPlay(). But this need a test to make sure it works.
You can defer begin play by overriding the basic functionality of the GameMode.
Override AGameMode::ReadyToStartMatch_Implementation in your gamemode class, and it will call beginplay when that function returns true.
If you need more direct control of beginplay, then override AGameMode::HandleMatchIsWaitingToStart() and don’t call Super::HandleMatchIsWaitingToStart(). Make sure you copy the original implementation into your own code so you’re not missing out on a call to the GameSession
You can then control exactly when BeginPlay is fired for all actors by calling AWorldSettings::NotifyBeginPlay().
Every actor can call GetWorldSettings()
EDIT: This will work when you want the entire world to start beginplay at the same time, but keep in mind that nothing ticks until BeginPlay() is called.
If you want to control BeginPlay on a per actor basis then you should set that bDeferBeginPlayAndUpdateOverlaps to true for as long as you need it.
Thanks. This confirm my suspicion from the previous post.