我如何构建我的摘要 类

How can I structure my abstract classes

我正在编写一个游戏,希望对我的 class 层次结构提出意见。

目前我有一个角色 class、一个 AICharacter class 和一个 KnightCharacter class。

Character 包含诸如 Death() 之类的所有角色都必须促进的东西,AICharacter 覆盖 Death() 并为 AI 驱动的角色提供额外的细节。 KnightCharacter 覆盖角色的东西,比如处理盾牌(仅适用于骑士)。

我怎样才能优雅地让我的玩家拥有一个 KnightCharacter : Character 而我的 AI 拥有一个 KnightCharacter : AICharacter : Character?

我基本上只想在 AICharacter 被 AI 控制时实现它。

谢谢

一种提供很大灵活性的方法是将您的角色和对象分解为多个方面,其中每个方面都是它自己的 class。动作或 RPG 角色可能具有的方面的一些示例包括 Health、Mana、WearsEquipment、UsesItems、MobileObject、PhysicalRigidbody、MeleeAttackPerformer、RangedAttackPerformer、MagicAttackPerformer、PlayerControlledMobile、AIControlledMobile,甚至诸如 AudioSource 等... classes 将派生自一个共同的基础,例如AspectMixin 或类似的东西。

如果您将这些 class 中的每一个都视为 Mix-ins,那么您在创建新原型时会获得很大的灵活性,这些原型具有对该类型的 actor 有意义的方面。这将允许,例如,怪物和玩家分享他们有健康的事实,但有不同的 classes 来控制他们(AI 控制与玩家控制)。此外,可以将健康方面添加到静止物体(例如桶),以使其受到损坏的影响。

为了实现这一点,您的原型对象存储了该原型的方面混合列表。此外,方面需要能够通过类型(或接口)查询其他方面的主要对象。设置起来有点麻烦,但这是灵活性的代价。

FWIW,这是 Unity 引擎试图鼓励的方法(考虑他们称它们为 MonoBehavior:行为..方面...同一概念的不同词),尽管许多开发人员并不 "get it" 直到他们制作了几个失败的原型,其中 classes 很快变成了整体。


回到你原来的问题,这有点取决于你有多少个可玩的 classes,以及 AI 是否可以控制相同 classes 的角色。如果是这样,最好从角色中抽象出控件,然后让 AIControl 和 PlayerControl 派生自控件,其中任何一个都能够与您的角色交互 class。

另一方面,如果 AI 类型可以分解为几种不同的行为(好斗的怪物、和平的 NPC),我会将每一种都作为一个方面。

普通的 C# 继承无法满足您的要求。你哥跟你爷爷不一样。

鉴于您似乎在寻找创意,这里有一个使用泛型的创意:

abstract class BaseController
{
    virtual GameEvent ReadNextEvent();
}

class PlayerController : BaseController
{
    override GameEvent ReadNextEvent
    {
        return userInterface.ReadNextEvent();
    }
}

class NonPlayerController : BaseController
{
    override GameEvent ReadNextEvent
    {
        artificialIntelligenceEngine.Think();
        return artificialIntelligenceEngine.ReadNextEvent();
    }
}

abstract class Character<T> where T : BaseController
{
    protected T controller;

    abstract ProcessEvents();
}

class KnightCharacter<T> : Character<T>
{
    override ProcessEvents()
    {
        var e = controller.ReadNextEvent();
        switch (e.Action)
        {
            1 : SwingSword(); break;
            2 : LiftShield(); break;
            3 : Yell("None shall pass!"); break;
        }
    }
}



class Program 
{
    void Example()
    {
        var playerKnight = new KnightCharacter<PlayerController>();
        var aiKnight = new KnightCharacter<NonPlayerController>();
    }
}