How do I get c++ inheritance working in actors when I can only inherit from non-UObjects?

3.4k views Asked by At

I am currently trying to implement inheritance like I would in any other project but I keep getting an error telling me that I can only inherit from non-UObjects or UInterface derived interfaces. I am trying to make a MasterEntity class that inherits AActor, and then I would have subclasses PlayerCharacter and NonPlayerCharacter that share certain variables like health, but I cannot get this seemingly simple task to work.

My current files are as follows

MasterEntity.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MasterEntity.generated.h"

UCLASS()
class THIRDPERSONGAME_API AMasterEntity : public AActor
{
    GENERATED_BODY()
    
public: 
    // Sets default values for this actor's properties
    AMasterEntity();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

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

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    int32 maxHealth;

};

PlayerCharacter.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Components/BoxComponent.h"
#include "InteractionInterface.h"
#include "MasterEntity.h"
#include "PlayerCharacter.generated.h"

UCLASS(config=Game)
class APlayerCharacter : public ACharacter, public AMasterEntity
{
    GENERATED_BODY()


public:
    APlayerCharacter();

    
protected:

    /** Called for forwards/backward input */
    void MoveForward(float Value);

    /** Called for side to side input */
    void MoveRight(float Value);

    /** 
     * Called via input to turn at a given rate. 
     * @param Rate  This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void TurnAtRate(float Rate);

    /**
     * Called via input to turn look up/down at a given rate. 
     * @param Rate  This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
     */
    void LookUpAtRate(float Rate);

protected:
    // APawn interface
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    // End of APawn interface

    virtual void BeginPlay() override;

    void OnInteract();

public:
    virtual void Tick(float DeltaSeconds) override;

private:
    UPROPERTY(EditAnywhere)
    UBoxComponent* InteractionBox;

    IInteractionInterface* Interface = nullptr;
};


What am I missing that will let me do this? I believe I can use components instead, but that seems really messy for what I am trying to do. I tried making the MasterEntity class just a regular C++ class and inheriting that, which didn't give me any compilation errors, but I wasn't able to see any values (like the maxHealth variable) from that in the blueprint editor.

2

There are 2 answers

0
Aayush Anand On

You just need to inherit from your custom class AMasterEntity. Since the custom class already inherits from the AActor class. This should work.

0
Manlok On

UE4 does not allow multiple inheritance from UObject-based classes (i.e. most UE4 classes you would want to use), but allows implementing multiple interfaces alongside inheriting from UObject. Avoiding "diamond inheritance" problem is one of the reasons behind that.

This is a common approach in a lot of programming languages and paradigms and helps manage state of your program. With multiple inheritance and possible diamond inheritances, state of your code can bloat rapidly in its complexity. Interfaces, unlike regular classes, do not bloat state of derived classes' objects, as they possess no data members.

In you example, you are trying to inherit from ACharacter and AMasterEntity at the same time, which both inherit from AActor, which is a UObject, hence the errors.

Using components would be the recommended solution, as it follows the "composition over inheritance" principle and prompts you towards writing less coupled and more reusable code (if done right).

I found it helpful to learn from Unity engine, which promotes these concepts even further: GameObjects (somewhat similar to UE4 actors) possess no code of their own and act purely as containers for MonoBehaviors (components), and C# language itself completely disallows multiple inheritance (aside from implementing interfaces).

Also, UE4 editor (and a lot of other UE4 functionality) relies on UPROPERTY(), UFUNCTION(), etc. macros to track structure of C++ classes, so without them it would not be able to display members of your class in blueprints, and these macros would not work outside of UObject-derived classes.