Download

How do you all avoid the "components owning components" pattern?

Looking for advice, whenever I make custom components I always feel like I am approaching it in the wrong way. I always end up wanting to give my components more sub-component functionality.

Simple Concrete example:
I was making an “InteractableComponent” so that anything with this component could potentially be interacted with.

I started inheriting from actor component but it would be nice to have some collision so that it can be detected by traces so I changed base class to USphereComponent. But now I would like to display some in-world text when the player is nearby so I guess I need TextRenderComponent functionality? I can’t have two base classes nor use sub-components so can’t come up with a clean solution. Should the interactable component add the TextRenderComponent to its owner and hold a reference to it?

I come across this problem often e.g. I want a component with collision but also a forward direction or particles so wondering how others structure their code to avoid duplicating code while keeping components “plug and play” i.e. they just work when attached to the actor without the owner needing to implement anything.

Thanks!

You can have two base classes in C++ with multiple inheritance. Unreal has special treatment of them as interfaces.

“You can have two base classes in C++ with multiple inheritance. Unreal has special treatment of them as interfaces.”

I’m not sure what this means. If you are saying that the OP can have his “interactableComponent” inherit from both USphereComponent and TextRenderComponent, that is not true. UE4 does not permit multiple inheritance based on UObject base classes.

The only way to achieve multiple inheritance in UE4 is to have your class inherit from a base class and then also inherit from an interface class. However, that won’t help you with respect to the components you reference, because those are UObject classes, not interface classes.

To accomplish what you are trying to accomplish, you could try this: Create the following classes:
InteractableComponent (inherits from USphereComponent)
TextRenderComponentActor (inherits from AActor)

In your custom ATextRenderComponentActor class, declare a UTextRenderComponent* variable and set the variable in the class constructor using the CreateDefaultSubobject function. Now this actor has a TextRenderComponent.

In your custom InteractableComponent class, declare an ATextRenderComponentActor* variable and, in BeginPlay, set the variable to a new instance of the ATextRenderComponentActor class.

Now, your InteractableComponent will have a USphereComponent as a component, and will also have a reference to an actor that contains a UTextRenderComponent.

One disadvantage of this approach is that you cannot set the value of your UTextRenderComponent in the Blueprint’s DefaultValues, because it doesn’t exist until BeginPlay.

I’d suggest not to mix too many responsibilities in a single component. For inheritance you’d typically ask the “is-a” question. In this case you’d probably respond to “Is an InteractableComponent a SphereComponent?” with the answer “No”. This becomes more obvious when you think about what would happen if you’d need the shape to be a BoxComponent instead at some point in the future. You’d end up rewriting InteractableComponent or end up with ugly situations where you now have a second InteractableComponent subclassing BoxComponent instead which will probably also contain lots of duplicated code from the first InteractableComponent.

Even though it’s more a manual process I’d just setup all the required components for each Actor class instead. This also gives you the flexibility to mix different Components as needed. So one Actor could have a SphereComponent, InteractableComponent and TextRenderComponent while another one has a BoxComponent and the InteractableComponent but no TextRenderComponent.

@UnrealEverything Thank you for your feedback, I take you point about the is-a relationship (inheriting from spherecomponent was more of a workaround). Maybe your suggestion is the best way to do it in Unreal so certainly good food for though I have to admit I am not a big fan since it is more manual as you say, also a lot less robust since every interaction component needs additional setup on the owner before it can work, if you change how interaction works you have to go through every actor and fix them, other team members are tempted to hijack support components for other uses etc etc.

@KelbyVP Thank you for your thoughts. Like you say it is not perfect but spawning a helper actor at runtime sounds like it will give me close to what I want. I will give it a try at least :smiley:

subclass an actor that has the different types of components that you need, and attach your interactive component to it. You don’t need your interactive component to have collision, you just need it attached to something that does have collision. So your Actor contains both the interactive component and the collision component, and the interactive component can query the Actor for it’s collision, if necessary. Or the actor can forward events from collision to interactive. Something like that.