Error on SpawnActor: Failed to Route BeginPlay

Hi all,

Got a really confusing bug here. I have a class named “AItemActor”, that derives actor. I have a function in a class called ActorManager that is responsible for spawning these. The rough process is: character performs an action, the character class then calls an RPC function to the server, passing the blueprint path of the item they want to spawn, server spawns it, and the actor is replicated. I get an error thrown immediately when the actor is spawned:

Script Stack:
CharacterEquipment.ServerEquipItem

[2018.07.21-21.20.40:914][151]LogOutputDevice: Error: Ensure condition failed: Component->HasBegunPlay() [File:D:\Build\++UE4+Release-4.19+Compile\Sync\Engine\Source\Runtime\Engine\Private\Actor.cpp] [Line: 3129] 
Failed to route BeginPlay (DamageHitBox /Game/Maps/UEDPIE_0_BasicPlayground.BasicPlayground:PersistentLevel.WoodenShieldActor_C_0.DamageHitBox)

If I hit f5 and ignore this, the actor does actually spawn fine, and I can continue with no problems. The next time an actor is spawned there is no problem at all, even when I end the session and restart. The bug only remanifests when I close the editor and start over. Obviously this error is thrown in the packaged version of the game too, and crashes it immediately with a fatal error.

The code and the rough steps are outlined below:

User presses a button. A function on the character class fires, leading to the following:

UFUNCTION(Server, Reliable, WithValidation)
void ServerEquipItem(ARoguelikeCharacter* character, LocationEnum location, FItemData itemData);
virtual bool ServerEquipItem_Validate(ARoguelikeCharacter* character, LocationEnum location, FItemData itemData) { return true; }
virtual void ServerEquipItem_Implementation(ARoguelikeCharacter* character, LocationEnum location, FItemData itemData);

This functions implementation makes a call that looks somewhat like this:

ActorManager->SpawnActorFromBlueprint(character->GetWorld(), deserializedItem->ActorBlueprint)

“ActorBlueprint” is of type TSubClassOf<AItemActor>.

The function then looks like this:

AItemActor* UActorManagement::SpawnActorFromBlueprint(UWorld* world, TSubclassOf<AItemActor> blueprint)
{
    return world->SpawnActor<AItemActor>(blueprint->GetDefaultObject()->GetClass());
}

This is the line that throws the above mentioned error. It will only happen the first time the call is made, and all pointers are valid and not null.

The following code is how I am loading the item itself, incase the loading of the blueprint isn’t quite correct:

UItem* UObjectSerializer::CreateItemFromPath(ARoguelikeCharacter* requester, FString assetPath)
{
    FStringAssetReference itemReference = assetPath;
    StaticLoadObject(UObject::StaticClass(), nullptr, *itemReference.ToString());

    UObject* itemObject = itemReference.ResolveObject();
    UBlueprint* itemBlueprint = Cast<UBlueprint>(itemObject);

    if (requester)
    {
        return NewObject<UItem>(requester, itemBlueprint->GeneratedClass, NAME_None, RF_NoFlags, 0, true);
    }
    else
    {
        return NewObject<UItem>(world, itemBlueprint->GeneratedClass, NAME_None, RF_NoFlags, 0, true);
    }
}

Any help would be hugely appreciated. Is this a replication error? Is there a better way for me to load items, instead of using paths?

AItemActor must have forgotten to call Super::BeginPlay()

That’s my suspicion as well.