Now forced to force call BeginPlay with NewObject

I used to have no problems with Unreal Engine lifecycle methods.

That being said for the following code.

void ASpawnerSupervisor::BeginPlay()
{
    Super::BeginPlay();
    
    // Clear singleton
	ASpawnerSupervisor::ASSp_SpawnerSupervisor = nullptr;
    // Reset singleton
    GetSS();
	
	

    ASSSLM1p_SpawnerSpaceShipLegionMark1 = NewObject<ASpawnerSpaceShipLegionMark1>(this); // Is this safe from begin play issue
	
	ASPUHp_SpawnerPowerUpHeal = NewObject<ASpawnerPowerUpHeal>(this);
	ASPUCWp_SpawnerPowerUpChangeWeapon = NewObject<ASpawnerPowerUpChangeWeapon>(this);

	// >>> This should not be required this is weird <<<
	// I have double check with logs and both ASPUHp_SpawnerPowerUpHeal and ASPUCWp_SpawnerPowerUpChangeWeapon
	// are initalized...
	ASPUHp_SpawnerPowerUpHeal->ForceBeginPlay();
	ASPUCWp_SpawnerPowerUpChangeWeapon->ForceBeginPlay();

    ASPUHp_SpawnerPowerUpHeal->ScheduledSpawn();
	ASPUCWp_SpawnerPowerUpChangeWeapon->ScheduledSpawn();

} 

All logs shows that everything is initialized properly (just for you know, I have also reput all concerned actors in game to make sure they do use my latests constructors)"

That being said, as you can see I need to call ‘ForceBeginPlay’ without it I can see that the log from the following code is never reached.

// Called when the game starts or when spawned
void ASpawnerPowerUpHeal::BeginPlay()
{
	
    Super::BeginPlay();
	f_ScheduledSpawnInterval = GetMS()->f_PowerUpHealInterval;
	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Orange, FString::Printf(TEXT("ASpawnerPowerUpHeal::BeginPlay  f_ScheduledSpawnInterval = %f "), f_ScheduledSpawnInterval));
	
	
    //f_ScheduledSpawnInterval = 5.0f;
}

void ASpawnerPowerUpHeal::ForceBeginPlay()
{
	BeginPlay();
}	

It is the first time I need to force call my BeginPlay and I don’t want the situation to be my new norm.

Anyone here can help me figure out how come I now need ForceBeginPlay() in order for BeginPlay() to be called? I except BeginPlay() to be automatically called after instantiating it.

Thx for your help

Because you shouldn’t be calling NewObject to create Actors. Instead you should get a UWorld (AActor::GetWorld should be fine in this case) and call SpawnActor.

Also, you should consider a using a WorldSubsystem for your supervisor instead. They are a better approach to singletons in Unreal than Actors you have to place or spawn into the leve.

2 Likes

Thx I will try that. Do you know when it’s proper to use NewObject ?

I confirm it works well with GetWorld SpawnActor.

Here is the revised code:

// TODO: Consider using WorldSubsystem 
// Called when the game starts or when spawned
void ASpawnerSupervisor::BeginPlay()
{
    Super::BeginPlay();
    
    // Clear singleton
	ASpawnerSupervisor::ASSp_SpawnerSupervisor = nullptr;
    // Reset singleton
    GetSS();
	

	ASSSLM1p_SpawnerSpaceShipLegionMark1 = Cast<ASpawnerSpaceShipLegionMark1>(OnDemandSpawn(ASpawnerSpaceShipLegionMark1::StaticClass()));
	ASPUHp_SpawnerPowerUpHeal = Cast<ASpawnerPowerUpHeal>(OnDemandSpawn(ASpawnerPowerUpHeal::StaticClass()));
	ASPUCWp_SpawnerPowerUpChangeWeapon = Cast<ASpawnerPowerUpChangeWeapon>(OnDemandSpawn(ASpawnerPowerUpChangeWeapon::StaticClass()));

    ASPUHp_SpawnerPowerUpHeal->ScheduledSpawn();
	ASPUCWp_SpawnerPowerUpChangeWeapon->ScheduledSpawn();

} 

AActor* ASpawnerSupervisor::OnDemandSpawn(TSubclassOf<AActor> TSOAAv_ActorClass)
{
    if (TSOAAv_ActorClass)
    {   
        
        FTransform FTv_SpawnTransform;
		
        FActorSpawnParameters FASPv_SpawnParams;
        FASPv_SpawnParams.Owner = this;
        FASPv_SpawnParams.Instigator = GetInstigator();

        AActor* AAp_SpawnedActor = GetWorld()->SpawnActor<AActor>(TSOAAv_ActorClass, FTv_SpawnTransform, FASPv_SpawnParams);
        if (AAp_SpawnedActor)
        {
           return AAp_SpawnedActor;
        }
        else
        {
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("AAp_SpawnedActor not spawned"));
           return nullptr;
        }
    }
    else
    {
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("AAp_SpawnedActor not set!"));
    }
    return nullptr;
}

When the type starts with a ‘U’. Types starting with ‘A’ are AActors and you need to use SpawnActor.