Undo/Redo doesn't work correctly with Actors spawned in C++

Hi,

I have lots of trouble getting the undo/redo feature to work with actors that are spawned in C++.
The actors I am spawning are BP classes that are derived from a native base class. I am spawning the actors like this:

AMyActor *actor = GWorld->SpawnActor<AMyActor>(actorBPClass, transform);

No problems noticeable so far, the actors spawn at the correct location and behave as you’d expect. Even undo/redo works for now. Unless you start editing the actors and want to undo that change …

  • move actor & undo: the actor is placed at (0,0,0)
  • delete actor & undo: the actor is placed at (0,0,0)

For some reason, these problems do not show up with all blueprint classes derived from AMyActor. The only hint I have so far is that more complex classes do work, while simpler classes don’t. Maybe it has something to do with the red ball icon (that I haven’t noticed before) that is displayed at the simple actors’ origin?

As a workaround I implemented Pre/PostEditUndo in our native class, restoring the transformation afterwards, but as objects dropped from the content browser do not have that problem, I am apparently missing something.
I stepped through the code and found that the problem is coming from the RerunConstructionScripts() function. In the cases when it doesn’t work (I just checked for delete + undo) there is no ActorTransactionAnnotation and the RootComponent’s ComponentToWorld does not contain the correct transformation, so the correct position cannot be recovered and the object is placed at the origin.

While the workaround helps with the placement, I also have a second problem which is even worse. I not only create the actor by code, I also destroy it there (using AActor::Destroy()). When I do this:

  • spawn, destroy, undo, destroy

the code crashes with an index out of bounds error in the USceneComponent::OnComponentDestroyed(). The reason is this: during the undo, the construction script is re-executed and attaches new child components to the actor’s root component. The problem is that most of the components (those that were added in the blueprint) already (or rather still) are attached and now are listed twice in the USceneComponent’s AttachChildren array. While looping over that array in OnComponentDestroyed() and detaching one of the duplicates from the parent, both entries are removed but index is only reduced by 1, hence giving it an invalid value beyond the last entry.

This problem only occurs when I delete the actors using AActor::Destroy() (I also tried GWorld->DestroyActor() with the same result). It does not occur when deleting them manually from the scene (using the editor interface), so I am apparently doing something wrong here as well. :frowning:

I hope someone has a solution or at least a hint (especially for the second problem) as I am out of ideas right now.

Thanks, Anselm

Hello,

As far as the second issue goes, this is a known issue that has been fixed internally and will be available in a later version. However, you can use the hotfix provided by Cø in this Answerhub post: Crash on closing PIE or BP - Multiplayer & Networking - Unreal Engine Forums
This hotfix has solved the crash issues for the users who are experiencing the same issue.