Bug with recreating an object that has subobjects

This came up as a result of mistakenly reusing the same name when spawning actors, however I believe there is nonetheless an underlying issue which should probably be looked at.

To repro, create an AActor derived class (named ATestActor in example below) with nothing added other than the following line in the constructor:

RootComponent = CreateDefaultSubobject< USceneComponent >(TEXT("TestSceneComponent"));

Then trigger the following code from any context:

auto World = GetWorld();
FActorSpawnParameters Params;
Params.Name = TEXT("MyTestActorName");
World->SpawnActor< ATestActor >(Params);
World->SpawnActor< ATestActor >(Params);

Clearly, reusing the same name like this is not something that should be done, however I suspect the results are not as intended. It will assert at check(!bHasBegunPlay); in UActorComponent::BeginPlay.

As far as I can see, calling NewObject with a name that already exists will recreate the object in place. However, there seems to be some issue with this process and subobjects - it seems they remain intact, giving rise to the above assertion failure.

At the very least, I think it would be a good idea to put a check for this scenario within SpawnActor and output a warning that the name has been reused.

Repro code:
TestActor.h
TestActor.cpp
LevelBlueprint

Hey -

How are you triggering the code block posted? Where is this being triggered from? Are you adding this to the custom class along with the first line of code? Where are “World” “ATestActor” and “TheActorClass” coming from? What exactly is the error you’re getting when doing this?

Cheers

Hi .
I’ve edited the question to clarify a couple of the names used.

The context from which the block of code is triggered can be anywhere, for example, invoke it from the BeginPlay event of any actor, or the level blueprint. Regardless of where it’s triggered from, calling SpawnActor multiple times using the same name, on an actor class which has components, will result in a crash - specifically the failed assert I mentioned.

I copied the “RootComponent” line into my actor class’s constructor and the other code block into the BeginPlay() function. After compiling and placing an instance of the class into the level I was able to PIE without getting any crash. Does copying the code into a new actor class in a new project give you the assert you mentioned? If so let me know if there is something I’ve missed in my reproduction.

I meant to put the triggering code into the BeginPlay of something else. I would have thought spawning the actor from within it’s own BeginPlay would have led to recursion problems.

Anyway, I’ve attached the code (on the original question) as I have it. This is all I’ve added to a blank project, along with the level blueprint set up as shown to trigger the spawning. No need to place an instance of the actor by hand.

Hey -

I was able to reproduce the crash you mentioned and a bug report (UE-20951) has been entered for investigation.

Cheers

You can get this to occur if you call BeginPlay within an AActor derived C++ class too (After it’s initial 1st call). I suspect that there is some initialisation / registration being done, and obviously the object has the same name as itself.