使用类作为事件标识符

本文关键字:事件 标识符 | 更新日期: 2023-09-27 18:27:37

我正在为视频游戏中的游戏对象开发状态机实现。我希望这个状态机使用起来简单;为了调用状态更改,应该在状态机上调用"Raise"方法。我目前的设计包括使用一个通用类型作为事件标识符:

stateMachine.Raise<Event>();

定义:

public void Raise<EventType>() where EventType : Event

然后,状态机找到处理此事件类型的状态,并根据它们提供的转换更新状态。我最初考虑使用字符串来识别事件类型,例如:

stateMachine.Raise("Event");

or和Enum:

stateMachine.Raise(GameObject.Event);

但我觉得这两种方法都会带来问题。字符串有两种灵活性,不能在编译时进行错误检查以确保它们是有效的。枚举无法扩展,限制了事件对每个扩展GameObject的类的可用性,使事件调用不必要地延长,并导致状态机内部的类型检查问题。然而,使用类作为标识的方法意味着我像这样声明GameObject内部的事件:

protected class SomeEvent : Event {}
protected class OtherEvent : Event {}
...
protected class AnotherEvent : Event {}

尽管很优雅,但我觉得这在某种程度上会成为一种代码气味或糟糕的做法,我觉得我在滥用类的目的。最终,我会有数百个空类散落在我的代码库中,我认为这是一个潜在的问题。什么才是最好的选择?

使用类作为事件标识符

由于您是为视频游戏编写的,除非这是游戏的一个功能,否则您的事件和状态应该在您的规范中定义,因此一旦定义,可能的事件列表就不应该移动太多;因此,选择源自共同祖先的类。

为什么不使用枚举或字符串?因为枚举和字符串不携带数据。你通常希望有一些数据与你的活动相关,因为它可以让你按家庭对你的活动进行分组。你不需要GrumpinessIncreaseEventJoyIncreaseEvent,而是需要一个包含一些信息的MoodChangeEvent(什么类型的情绪受到影响,受影响程度等)

更重要的是,您可以拥有一些松散类型的事件,用于以后可能拥有的潜在已知未知(例如,具有对象属性的事件,然后在运行时转换为某种类型)


re:OP评论:我确实认为应该使用实例而不是类型。你不会通过PunchInFace,而是通过new DamageEvent() {type = Damage.PUNCH, source= PuncherGuy.Fist, Target=PunchedGuy.Face},因为这种事件对游戏中的许多组件(物理引擎、分数引擎等)更友好

再一次,这取决于游戏是如何完成的(这让我认为这个问题实际上应该结束,因为它是基于意见的),但当你按类型提出PunchInFaceEvent时,你能说什么?谁打了谁?哪里什么时候等等。