Setting a root Scene Component that's not a subobject

Hello !

Context

I’m currently trying to work with Actors that need a Primitive Component directly as their root.

The thing is, I don’t know whether that Primitive Component is for a Static Mesh or for a Skeletal Mesh beforehand. It depends on external parameters, and may change with each instance of the Actor class.

Now, since UPrimitiveComponent is abstract, I can’t create it as a subobject in the Actor constructor, and define it as the root there. So what I’m doing instead is :

  • dynamically creating the correct Component with NewObject when I do know what specialized class I want
  • making sure it gets owned by my Actor, registered in the world, etc.
  • setting is as the new root, while reworking the rest of the Component hierarchy to fit my needs

This strategy works quite well, as long as my Actors are instantiated dynamically.

But then I tried to serialize them into Blueprint Actors, and that’s when it started to get tricky.

Issue

First, it seems like the Primitive Component doesn’t get saved as the root inside the BP. I had to act on PostInitializeComponents to enforce the Component hierarchy I really wanted. Not ideal (because it’s called a lot) but at least, the Blueprints seemed to be okay, like this.

And then I discovered that adding a new C++ scene component, as a subobject of my class, would break the hierarchy shown in editor.

Here’s what I observe in more details :

  • The additional scene component subobject, even if not set as root, becomes the first root anyway because of FixupNativeActorComponents. So far, I get why, and it’s not supposed to be an issue.
  • The code I put on PostInitializeComponents is called, and - seemingly - manages to fix the hierarchy. It does set the Primitive Component as the root, and the additional scene component as a child.
  • But the editor still shows the scene component subobject as the root. It’s simply not showing the structure I observe through my debugger, or even through logs…

Questions

Well, first, why do I get different truths from the editor and the debugger/logs, when it comes to the Component hierarchy?

Also, is there any other safe way for me to generate those Blueprints while inheriting from a class that doesn’t want to specify the exact type of its root Component? Any workaround?

Thanks for your answers.

Hi!

Unreal isn’t set up to handle dynamic components at C++ Construction time; the CDO needs to remain fully static/deterministic, representing in-memory what the uasset looks like on disk. You would either need to have it contain both components and then disable the one that isn’t used at runtime, or to just spawn the dynamic component at runtime, such as during BeginPlay, which is the method I’d choose.

If you want to build on the hierarchy by extending BP classes, I recommend not setting the dynamic Mesh/SkelMesh component as the root. Instead, use either an empty SceneComponent or a collision shape as the root component and then attach the Mesh/SkelMesh component to that one at runtime.

Thanks for your answer!

To be clear, my goal is to have a tool that produces Bluprints, on disk, that can be modified by the team afterwards. I have code that creates the Actor, dynamically adds the component and set is as root. But indeed, it seems like having a root which is only identified at deserialization, far after construction, is not really possible.

I’ll probably end up adding a native root Component. Even though it’s really a bother for my need, I can still work around that.

What I’m really failing to get, though, is the following : In PIE, after my code changes the root, the editor fails to show that the current root Component is the dynamic one. Why is that? It it just that it doesn’t refresh after the CDO first figures out the hierarchy?

Your goal should work, if you can decide which component you add when serializing the Blueprint’s asset.

You’re probably not seeing the runtime added components in the outliner because runtime added components are hidden by default. To be able to inspect components that were only added to an actor during runtime, uncheck Editor Preferences -> Content Editors -> Blueprint Editor -> Hide Construction Script Components in Details View.

Yes, I do know which component to add before serializing the BP.

Unfortunately, if I want that Component to be the root, everything falls apart. The BP I create doesn’t really manage to keep that Component as its root.

Typically, let’s say I add a C++ scene component to the Actor class AFTER my BP is created and saved (supposedly with the runtime added Component as root). Then, when I open my BP, I see that the C++ component has been forcefully set to the new root.

Oh, there’s been a misunderstanding. I do see the runtime added component alright! It’s just not shown as the root, even though a simple call to “GetRootComponent” will answer that it indeed is the root.

Basically, I was getting in a situation where I could observe this :

Editor outliner :

  • Root : C++ Scene Component
    • Child : Blueprint Primitive Component (added dynamically and then saved into a Blueprint asset)

Dynamic logs :

  • Root : Blueprint Primitive Component (added dynamically and then saved into a Blueprint asset)
    • Child : C++ Scene Component

Usually, BPs are only used to add components to what the C++ class declares, not move them around. Maybe Unreal is acting weird because of that. I feel that this dynamic BP asset creation may be overcomplicating things, as it goes against the “Unreal way.”

I wonder if just diverging earlier, in C++, would work better for your use case?

ABaseFooBar : public AActor // contains all shared basic functionality
AStaticMeshFooBar : public ABaseFooBar // Static mesh version of FooBar
ASkelMeshFooBar : public ABaseFooBar // Skeletal mesh version of FooBar
 
BP_ActorInstanceThatNeedsStaticMesh : parent class AStaticMeshFooBar.
BP_ActorInstanceThatNeedsSkelMesh : parent class ASkelMeshFooBar.