我正在为视频游戏中的游戏对象开发状态机实现。我希望这台状态机易于使用;为了调用状态的变化a'提升'应该在状态机上调用方法。我目前的设计涉及使用泛型类型作为事件标识符:
stateMachine.Raise<Event>();
定义:
public void Raise<EventType>() where EventType : Event
状态机然后找到处理此事件类型的状态,并根据它们提供的转换更新状态。我认为最初使用字符串来识别事件类型,例如:
stateMachine.Raise("Event");
或和Enum:
stateMachine.Raise(GameObject.Event);
但我觉得这两种方法都存在问题。字符串是两个灵活的,无法在编译时进行错误检查,以确保它们有效。枚举不能被扩展,限制扩展GameObject的每个类可用的事件,使事件调用更长时间不必要,并导致状态机内的类型检查问题。但是,使用类作为标识的方法意味着我在GameObject中声明事件,如下所示:
protected class SomeEvent : Event {}
protected class OtherEvent : Event {}
...
protected class AnotherEvent : Event {}
尽管优雅,但我觉得这在某种程度上会变成代码气味或可怕的做法,我得到的印象是我滥用了课程的目的。最终我将有数百个空类乱丢我的代码库,我可以看到它是一个潜在的问题。什么是最好的选择呢?
答案 0 :(得分:1)
由于您正在为视频游戏而写作 - 除非这是游戏的一项功能 - 您的事件和状态应该在您的规范中定义,因此可能的事件列表一旦定义就不应该移动很多;所以去那些来自共同祖先的课程。
为什么不使用枚举或字符串?因为枚举和字符串不会携带数据。您通常希望将某些数据与您的活动相关联,因为它可以让您按家庭对活动进行分组。您不需要GrumpinessIncreaseEvent
和JoyIncreaseEvent
,而是MoodChangeEvent
,其中包含一些信息(受影响的情绪类型,影响程度等)
你还可以拥有一些松散类型的事件,这些事件可以用于以后可能具有的潜在已知未知数(例如,具有对象属性的事件在运行时被转换为某种类型)
re:OP的评论:我的确认为你应该使用实例而不是类型。你不会通过PunchInFace
而是new DamageEvent() {type = Damage.PUNCH, source= PuncherGuy.Fist, Target=PunchedGuy.Face}
,因为这种事件对游戏中的大量组件(物理引擎,得分引擎等)更友好......
再一次取决于游戏是如何完成的(这让我觉得这个问题实际上应该是关闭的,因为它是基于意见的)但是当你按类型提出PunchInFaceEvent
时,你能说什么呢? ?谁打了谁?哪里?什么时候?等...