Class inheritance software design question

Hi!

I’m using Unreal 5.3.2.

I have a question about software design.

In my game there are two levels with ten different actors each. These actors have this parent class:


public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(..., Category = "Components")
	UStaticMeshComponent* BodyMesh;

	UPROPERTY(..., Category = "Components")
	class UTextRenderComponent* BodyName;

	UPROPERTY(..., Category = "Components")
	FString OtherName;

};

I can use these ten classes in both levels with one difference: In both levels I use the BodyMesh property, but in one of them I use BodyName only and in the other one I use only OtherName.

Maybe, I could use these ten classes in both levels, but the problem is that maybe I will need to specialise more these ten classes for one level, but I will still using them in both.

Is it better to have ten classes for both levels or twenty classes (ten for each level)?

Probably I’m overthinking about this.

Thanks!

In object oriented programming there is a principle called “Composition over inheritance” which alleviate the problem of inheriting things you don’t need.
Common behavior is still convenient to inherit though and more specialized behavior could be encapsulated within components.
Interfaces can also help with keeping inheritance and composition cleaner.

This is pretty good explanation of the Composition and Inheritance difference in Unreal.
The first part regarding Unity can be skipped.

Ravens answer here is correct, I have only one caveat. Actor Components are considerably more expensive than UObject. And in this particular use case you wouldn’t need the extra capabilities of Actor Component, unless you need replication.

I was evaluating composition, and if I were to use it it would mean having to manually add an UTextRenderComponent in each of the 10 child classes.

You could perhaps make a blueprint library with a static function that would work as a factory. Just pass in the class via reference and it could build out the needed components at runtime.

Though these new components would be dynamically created with newObject so it would be harder to access them from with the code.
You could perhaps:

  • dynamically bind them to delegates
  • fill in uproperties that start off as uninitialized nullptr (not ideal)