首页 > 解决方案 > 当我只能从非 UObjects 继承时,如何让 c++ 继承在演员中工作?

问题描述

我目前正在尝试像在任何其他项目中一样实现继承,但我不断收到错误消息,告诉我我只能从非 UObjects 或 UInterface 派生接口继承。我正在尝试创建一个继承 AActor 的 MasterEntity 类,然后我将拥有共享某些变量(如健康)的子类 PlayerCharacter 和 NonPlayerCharacter,但我无法完成这个看似简单的任务。

我目前的文件如下

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;

};

玩家角色.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;
};


我错过了什么可以让我这样做?我相信我可以改用组件,但这对于我正在尝试做的事情来说似乎真的很混乱。我尝试使 MasterEntity 类只是一个常规的 C++ 类并继承它,这没有给我任何编译错误,但我无法在蓝图编辑器中看到任何值(如 maxHealth 变量)。

标签: c++unreal-engine4unreal-blueprint

解决方案


UE4 不允许从UObject基于 的类(即您想要使用的大多数 UE4 类)进行多重继承,但允许实现多个接口以及从UObject. 避免“钻石继承”问题是其背后的原因之一。

这是许多编程语言和范例中的常用方法,有助于管理程序的状态。使用多重继承和可能的菱形继承,代码状态的复杂性会迅速膨胀。与常规类不同,接口不会膨胀派生类对象的状态,因为它们没有数据成员。

在您的示例中,您试图同时继承ACharacterAMasterEntity继承,它们都继承自AActor,这是 a UObject,因此出现错误。

使用组件将是推荐的解决方案,因为它遵循“组合优于继承”的原则,并提示您编写更少耦合和更可重用的代码(如果做得好)。

我发现向 Unity 引擎学习很有帮助,它进一步推广了这些概念:GameObjects(有点类似于 UE4 角色)没有自己的代码,纯粹充当MonoBehaviors(组件)的容器,而 C# 语言本身完全不允许多重继承(除了实现接口)。

此外,UE4 编辑器(以及许多其他 UE4 功能)依赖于UPROPERTY()、、UFUNCTION()等宏来跟踪 C++ 类的结构,因此如果没有它们,它将无法在蓝图中显示您的类的成员,并且这些宏将不起作用在 -UObject派生类之外。


推荐阅读