Make C++ class hierarchy beginning with AActor and ending with APawn

I want to simulate the space and am using the classes VisibleObject (i. e. planets, are assumed not to move), MovingObject (e. g. comets), and SpaceShip (can accelerate with rockets). So I have the hierarchy VisibleObjectMovingObjectSpaceShip.

Because the simulation shall be efficient, the objects do not handle their movement themselves by ticks, instead there is a pure C++ class Universe, that calculates everything for them (amongst other things: collisions by using the member variable collisionRadius from VisibleObject).

At the moment my SpaceShip is just an actor and uses

InputComponent = NewObject<UInputComponent>(this, "BattleshipInput");
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
EnableInput(PlayerController);

in BeginPlay for getting key and mouse input. This comes with the following problems:

  • I made a GameMode blueprint and cannot chose my Spaceship to be the default pawn.
  • I made a blueprint based on Spaceship and cannot get the inputs in the event graph. (Only in the C++ class directly.)

There may come other problems in the future. So my question is: When VisibleObjects inherits from AActor, how can I make my SpaceShip be a pawn? How should I (re)structure my classes or my Unreal project to get this work?


And besides: How can I force an instance of Universe to be a mandatory “member” of a level, including executing/receiving ticks? For now Universe is a member of my GameMode, what doesn’t seem to be elegant and could make problems later, because I read, that GameMode calculations are done by the server in a multiplayer game. (This is just a little extra question, don’t worry. In case of need I would open a new thread on UE answerhub.)

Why dont you use Interfaces or Component based Design? You dont have to solve everything with Inheritance. If you just need Inputs from a Pawn (even Better your Controller) forward it to where you need it. Your Ship itself does not have to be a Pawn and you Handle Movement etc. yourself there is “not much” benefit for you to get out of the Pawn Class.

Since its a Design Question and can be solved in multiple ways here some things to look up:

Design Patterns, Encapsulation, OOP best Practices, Composition over Inheritance, Abstraction.


Your Bonus Question: Make the Universe a Singleton or use Game Instance that is already a Singleton.

Using AGameStateBase for handling global ticks is the solution for my bonus question, thanks Erdrik. I won’t deal with Multiplayer in the near future, so that’s fine for now.

I edited my question to be more precise about what my problem is. What exactly do you mean with “then you can hide the pawn, remove its collision and attach it to the SpaceShip”?

GameInstance or singletons inheriting from AActor seem to be other solutions for my bonus question, including making ticks.

Do you mean using UInputComponent from AActor (like I did) is a good way for me? I just edited my question to make the problem clearer.

Mhh nope simply use the InputComponent from your Controller. Send the Input forward to your universe or the Movable Object you want.

virtual void SetupInputComponent();

override it and

PushInputComponent(yourInputComponent)

You are going to need to make a new class that inherits from APawn.
This will unfortunately mean your pawn will not directly inherit from your VisibleObject → MovingObject → SpaceShip hierarchy. However, if all you need is the inputs from the player, then you can hide the pawn, remove its collision and attach it to the SpaceShip. Then pass any interaction from the pawn to the Spaceship.

Do you intend for this simulation to have multiplayer?
Im not sure how replication of UObjects is handled as compared to AActors(since I primarily use AActor inherited classes), but a custom GameState could track and replicate the Universe (tho Im not sure what Universe inherits?) if you need it to be on both Server and Client.
When I set the following variables in the constructor of my AActor derived classes they auto spawn for the client when spawned on the server:

SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
bReplicates = true;
bReplicateMovement = true;
bAlwaysRelevant = true;
bNetLoadOnClient = true;

Sorry that this took a while.
The answer is: No, UE does not support inheritance as known from C++. Neither my desired hierarchy nor even only interfaces, as these cannot use variables and cannot be implemented directly.

So, as Nachtmahr suggested, my solution was composition over inheritance. Technically, I inherited from UMovementComponent. That’s not optimal, but at least the best Unreal offers.