Crash spawning actor from template

Hello

I have a reproducible case of an assert when trying to spawn an actor from a template

For my game I am trying to spawn a duplicate of an actor at runtime, with deep copy of its subobjects, in particular the custom components necessary for my game logic.

However, trying to call UWorld::SpawnActor(UClass*,FTransform const*, const FActorSpawnParameters&) with an actor template that contains a component added in the editor will result in an assert.

Am I doing something wrong?

I traced through execution of what seemed a perfectly reasonable instanciation of subcomponents, although the recursion seems to make it reallocate its own array by adding an element in an inner loop with integrity check.

The actual assert happens at PropertyArray.cpp line 338 after successfully instanciating the subobjects including the actor components:

checkf(DestValue == ArrayHelper.GetRawPtr(ElementIndex), TEXT("%s has been re-allocated while instancing subobjects for %s, fix higher level code!"), *GetName(), *Owner->GetPathName());

Here is an example of how to reproduce the problem quickly:

In a UBlueprintFunctionLibrary header file :

UFUNCTION(BlueprintCallable, Category = "Test")
	static AActor* SpawnActorFromTemplate(AActor* anOwner, AActor* aTemplate, const FTransform aTransform, ESpawnActorCollisionHandlingMethod aCollisionHandling = ESpawnActorCollisionHandlingMethod::AlwaysSpawn);

.cpp

AActor* UProjectStatics::SpawnActorFromTemplate(AActor* anOwner, AActor* aTemplate, const FTransform aTransform, ESpawnActorCollisionHandlingMethod aCollisionHandling /*= ESpawnActorCollisionHandlingMethod::AlwaysSpawn*/)
{
	if(anOwner && aTemplate)
	{
		FActorSpawnParameters params;
		params.Template = aTemplate;
		params.SpawnCollisionHandlingOverride = aCollisionHandling;
		params.ObjectFlags = RF_Transient;

		return anOwner->GetWorld()->SpawnActor(aTemplate->GetClass(), &aTransform, params);
	}

	return nullptr;
}

Create a new level and add any static mesh actor and a component, here I used a PointLightComponent

Add the testing code in level blueprint:

What am I doing wrong? What is the correct way to duplicate actors with deep copy of subobjects at runtime?

Thanks in advance!

Please note that this is also mentioned in an official documentation page, however considering my observations, this code would fail if the existing actor has components.

The NewObject and SpawnActor functions
can also be given a “template” object
to work with. Unreal will make a copy
of that object, instead of making one
“from scratch”. This will copy over
all of its UPROPERTYs and components.

AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor, FVector SpawnLocation, FRotator SpawnRotation)
{
    UWorld* World = ExistingActor->GetWorld();
    FActorSpawnParameters SpawnParams;
    SpawnParams.Template = ExistingActor;
    World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
}

Hello,

Could you provide your crash logs, as well as your Machine ID, which you can find in the Crash Reporter window that appears when your project crashes. Also, ensure that you hit Send on the Crash Reporter window.

I was not able to reproduce your issue in my project. I used your exact setup, and my actor spawned without issue, so I’ll need the above information to begin looking into this issue. Thank you.

You should create a Blueprint with the components attached and not an arbitrary actor in the level. Then you spawn that BP class and it should work fine

Hello thanks for taking the time to look at this.

First of all I would like to mention that this has been reproduced in an empty project and clean engine by a member of the community on IRC. I am definitely not an isolated case. Bear in mind the component on the actor is not added to the blueprint template, but to the actor instance in the level.

Unfortunately my crash reporter does not seem to work tonight but I will be working on providing you a report asap. I am confident you can reproduce this using my setup as long as the template actor is an instance and has an extra component.

In the meantime here is the callstack of the assert: UE4Editor-Core.dll!FOutputDeviceWindowsError::Serialize(const wchar_t * Msg, E - Pastebin.com

I did some more digging and it turns out that this assert can sometimes be bypassed by using deferred construction to spawn the actor. Strangely I had this yesterday but couldn’t get past it today. It could be because of upgrading to 4.10.1

It then asserts during BeginPlay(), the reason being that the components have in fact not been copied but only transferred from the template to the newly created actor, and those components already did begin play. Strangely, the components are not copied from the template actor and this is observable: during the constructor call at UObjectGlobals.cpp(2000)

new ((void *)Obj) UObjectBase(InClass,InFlags,InOuter,InName);

This was also the reason for the assert mentioned in my first post: the array we are iterating upon has been cleared and its components transferred to the newly spawned actor.

Should SpawnActor() be able to use instances as a template for replication, instead of a template from an asset? If not, then I would suggest an assert guard and/or a comment to indicate this. FActorSpawnParameters::Template is rarely used in the source code and never with an actor instance.

Most importantly is there any other way to spawn a clone of any actor at runtime? We have introspection and serialization, it should be doable.

This is a different use case. You are spawning from a class template, while I want to use an instance as template. In your case you would not be using the FActorSpawnParameters::Template parameter.

I misunderstood your callstack. You’re right that something funky with subobject instancing is going on

I understand all of that. I am explicitly trying to duplicate the actor which has the level as outer, at runtime, with no intent to save it.

There is in fact nothing to indicate that you should not pass this as a FActorSpawnParameters::Template. The documentation I linked above even suggests this to clone actors, albeit not mentioning which types of actors are valid parameters.

If this actor is not a valid parameter then an assert or a comment would make that clear, but otherwise there is no reason to believe this can not be done, again we have serialization, making a copy of any object is possible.

In fact this works perfectly fine up until the point where you add a component into the mix. If anything this is inconsistent behavior.

Hello,

I have investigated this issue, and been able to reproduce it using the information you have provided. I have entered a bug report (UE-24372) regarding the crash when duplicating an actor that contains components added to an instance in the level.

Have a great day,

Flint

Thank you so much.

In the mean time, is there a workaround that you know of to achieve a similar result?

The only thing that I can recommend at this time would be to add the components to the blueprint rather than add them to an instance of the actor in the level. This seems to be what was causing the issue, so avoiding this if at all possible would be best.

I got a similar crash for spawning actors from templates with components added to them.

I got the following code in which i am crashing (UObjectGlobals.cpp):

			while (!Obj->IsReadyForFinishDestroy()) 
			{
				// If we're not in the editor, and aren't doing something specifically destructive like reconstructing blueprints, this is fatal
				if (!GIsEditor && FApp::IsGame() && !GIsReconstructingBlueprintInstances)
				{
					UE_LOG(LogUObjectGlobals, Fatal, TEXT("Gamethread hitch waiting for resource cleanup on a UObject (%s) overwrite. Fix the higher level code so that this does not happen."), *OldName );
				}
				FPlatformProcess::Sleep(0);
			}

As from what i observed most actors with components will cause a crash on this line. The reason is the fact that all these components use a fence during destruction i believe. The code assumes that this will not be the case and destruction should happen immediately.

Example:

bool ULightComponent::IsReadyForFinishDestroy()
{
	// Don't allow the light component to be destroyed until its rendering resources have been released
	return Super::IsReadyForFinishDestroy() && DestroyFence.IsFenceComplete();
}

Solved by:

On the line just above spawning the actor put the following code:

AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor, FVector SpawnLocation, FRotator SpawnRotation)
 {
     TGuardValue<bool> GuardTemplateNameFlag(GIsReconstructingBlueprintInstances, true);
     UWorld* World = ExistingActor->GetWorld();
     FActorSpawnParameters SpawnParams;
     SpawnParams.Template = ExistingActor;
     World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
 }

Answer:
This line ensures it does not crash and so far i didn’t find any issues with it.

Hello guys,

Is there any progress on that? I have experienced the same issue in 4.12. The bug report status of UE-24372 is Cannot Reproduce. Do you need more details in order to reproduce it?

I am able to provide a full repro case in an isolated project if needed. This should not be difficult to reproduce indeed, and if was able to, it should not be “cannot reproduce” :slight_smile:

Ditto to all the above. I just reproduced this as well.

EDIT: I spoke too soon. I’m not seeing the original behavior. But I am seeing all kinds of things not working in various ways. I’ll see if I can make a small test project to share.

Hey everyone,

Could you please provide a full set of repro steps so I can reproduce this in 4.13? The original repro no longer reproduced the crash on my end.

Thanks

I’ve created a project that repros the problems I’m seeing: https://drive.google.com/open?id=0B7RB2LREc53IeVplV3BsTk1yWEk

There are two spawners in this scene. The class spawner which spawns things normally through SpawnActorFromClass, and the instance spawner, which uses SpawnActorFromTemplate using the code provided in the bug report. SpawnActorFromClass is simply there to show the desired behavior. Both spawners show debug boxes where the actors are trying to be spawned.

Issues I’m seeing with the Instance Spawner:

  • Actors are spawned and exist in the outliner, but they are not visible.
  • Spawning an actor with a procedural mesh component with “Use Complex as Simple Collision” disabled will crash unreal.

Hey ,

Thanks for the project. I was able to see what you see (in regards to the Procedural Mesh causing a crash when used in the template class) and have created a issue report for it.

You can follow it here:

https://issues.unrealengine.com/issue/UE-37429

For now, I would recommend using the Spawn Actor from Class Blueprint node over yours.

Thanks. Unfortunately, that doesn’t help me as I was trying to avoid incurring the cost of copying a static mesh component to the procedural mesh component every time I spawned an identical procedural mesh at runtime.

Were you able to reproduce the other problem - that SpawnActorFromTemplate doesn’t create visible actors?

I have and I don’t think it’s a bug with the engine. I think it has to do with the FActorSpawnParameters.

Can you try the following and see what happens?

AActor* UTFunctionLibrary::SpawnFromTemplate( AActor *Template, FTransform Location, ESpawnActorCollisionHandlingMethod aCollisionHandling /*= ESpawnActorCollisionHandlingMethod::AlwaysSpawn */ )
{
	if( Template )
	{
		FActorSpawnParameters Params;
		Params.SpawnCollisionHandlingOverride = aCollisionHandling;
		const FVector Loc = Location.GetLocation( );
		const FRotator Rot = Location.GetRotation( ).Rotator( );
		return Template->GetWorld( )->SpawnActor( Template->GetClass( ), &Loc, &Rot, Params );
	}
	return nullptr;
}

Thanks.