Download

Problem adding child SceneComponents to another SceneComponent in C++

Hey guys. I have an ACharacter with a custom component that inherits USceneComponent, which itself has two UPROPERTY fields for base USceneComponents. Nothing too complicated, this is the hierarchy:

-Character

–CustomSceneComponent

—SceneComponent1

—SceneComponent2

The intention is for CustomSceneComponent to use the relative positions of SceneComponent1 and 2 to show things relative to character. This seems pretty straightforward, and these items appear in the correct hierarchy in the Blueprint Editor Viewport, but I’m unable to move SceneComponent1 or SceneComponent2 - the gizmo simply ignores any attempt I make to drag it in any direction. I’m not sure where along the way I’ve gotten it wrong. Dragging around the CustomSceneComponent itself works perfectly fine.

Here’s what my declarations in CustomSceneComponent.h look like

This is the code I’m using to create the components in the constructor of CustomSceneComponent

Here’s what the hierarchy looks like in the Blueprint Editor. Everything behaves as expected except for High/LowIndicatorTransform

If I’m missing enough info to describe my problem, or if I’m simply approaching this the wrong way altogether, (this is essentially what I’d do in Unity) let me know. I’ve spent a few hours trying different things and getting results of varying strangeness, and I’m pretty close to just replacing the child USceneComponents with simple FVector position fields, which I think is pretty lame!

Thanks

Excuse me if I’m way off, it’s been a long time since I’ve dealt with UE4. Just got back into it recently, but it may be because of your UPROPERTY specifier of VisibleAnywhere. Try it with EditAnywhere in it’s place. VisibleAnywhere allows you to see it in a BP, but cannot be edited.

Thanks for the reply, Novithian!

I gave it a shot just to be sure, but from the looks of it, setting it to EditAnywhere vs VisibleAnywhere just means that I can change what the instance of what the UPROPERTIES point to. IE, I can change the property from a USceneComponent to anything else that inherits from USceneComponent, such as a Capsule Component or an Arrow Component. It affects my ability to change what the property is, but doesn’t seem to have an effect on my ability to modify fields on the property.

I’d like to enforce that SceneComponent1 and 2 are both single instances of USceneComponent, but the engine just doesn’t like something about the way I’m going about it. What’s more annoying is that if I add a Scene Component via the Blueprint Editor as a sibling of the inherited Scene Components, that instance behaves totally normally, despite having no major differences from the inherited instances that I’m able to perceive.

I’m also having a really hard time trying to find an example of anyone else trying to do the same thing on the internet. I’m already at the dreaded point where Googling how to do what I want to do brings up this very thread as one of the top results. Is using nested Scene Components as a way to define hierarchical transforms really such an out-there approach? What’s the “right way” if not that?

Wait, are those two components being created by their parent component’s constructor? If so, that is definitely not standard and I’m even surprised it worked at all. Since the Actor doesn’t “own” those sub-components, it has no way to override their properties. The three components should be created from the Actor’s constructor, AFAIK.

Well, indeed that appeared to be the bone Unreal had to pick with my Scene Components. Moving the creation code to the Actor’s constructor and making a public setter for my custom USceneComponent class gives me 2 well-behaved Scene Component children.

I do think this sucks for a couple of reasons. Every Actor class that utilizes this custom component is now responsible for instantiating these children, and in this particular case, creating ArrowComponents for these children so that they’re visible. I think it’d be much better if I could simply add the custom component, and said component knew how to instantiate all of the other components it requires to operate. Thinking about it though, I guess that opens up the potential for some sort of crazy recursive issues if a USceneComponent’s constructor is told to instantiate another instance of itself? Not that you can’t already shoot yourself in the foot in a myriad of ways through UE4.

If anyone is aware of a solution that works a bit more similar to my original approach, that’d would be great to know about. But in the meantime, this allows the Blueprint Editor itself to be just as bulletproof, so I’m happy with it for now, and much happier than I would have been with FTransform fields for sure).

Thanks!

Creating SceneComponents in another SceneComponent’s constructor works just fine using “CreateDefaultSubObject”. I’ve shipped multiple projects with arbitrarily deep mesh component topologies. Like this:

Actor>>Component>>SubComponent>>SubSubComponent>>SubSubSubComponent

There’s nothing special aside from making sure that no two components has the exact same FName because it causes issues in the Editor details window.

Interesting, not sure what to say about that! The code in my first post shows that the USceneComponents I was instantiating had unique names, and the only way to get it to stop being broken was to simply move the exact same code out of the USceneComponent’s constructor and into the AActor’s constructor.

If you’re willing to share an example of one of the cases wherein you successfully spawned USceneComponent hierarchies from the constructor of a single derived USceneComponent class, maybe that could highlight something that I was doing incorrectly. Aside from that though, I have no idea why the Blueprint Editor took such issue with me doing exactly what I was doing in my first post.

You’d need to go into the code that deals with AActor serialization and editing to figure out if there’s anything you can do. Maybe a combination of flags or something in the PostInitComponents could trick the editor into allowing you to override those.