我如何构建我的摘要 类
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>();
}
}
我正在编写一个游戏,希望对我的 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>();
}
}