到目前为止,我所使用的实体组件系统的工作原理基本上类似于Java的artemis:
- 组件中的所有数据
- 无状态独立系统(至少达到在初始化时不需要输入的程度)对仅包含特定系统感兴趣的组件的每个实体进行迭代
- 所有系统都处理它们的实体一tick,然后整个过程重新开始。
现在,我尝试将其首次应用于基于回合的游戏,在继续进行之前,必须以相对于彼此的固定顺序进行大量事件和响应。一个例子:
玩家A受到剑的伤害。对此,A的装甲可以踢进并降低受到的伤害。由于变得越来越弱,A的移动速度也会降低。
- 所遭受的损害是引起整个互动的原因
- 必须先计算护甲并将其应用于即将来临的伤害,然后再将伤害应用于玩家
- 直到实际造成伤害之后,才能将移动速度降低应用于某个单位,因为它取决于最终伤害量。
事件还可以触发其他事件。使用装甲减少剑的伤害会导致剑破碎(这必须在伤害减少完成之前进行),进而会引起其他事件,这实际上是对事件的递归评估。
总而言之,这似乎导致了一些问题:
- 很多浪费的处理周期:大多数系统(保存总是运行的东西,例如渲染)在没有“轮到他们”工作的时候根本没有任何值得做的事情,并且花费大部分时间等待游戏进入有效的工作状态。这会给每个这样的系统带来很多麻烦,随着越来越多的状态添加到游戏中,这些检查会不断增长。
- 为了确定系统是否可以处理游戏中存在的实体,他们需要某种方式来监视其他不相关的实体/系统状态(负责处理损害的系统需要知道是否已使用装甲)。这要么使系统承担多重责任,要么产生对其他系统的需求,而没有其他目的,只能在每个处理周期之后扫描实体集合,并通过告诉侦听器何时可以做某件事与一组侦听器进行通信。
以上两点假设系统在同一组实体上运行,最终使用其组件中的标志更改状态。
解决此问题的另一种方法是,由于单个系统的工作而增加/删除了组件(或创建了全新的实体),从而提高了游戏状态。这意味着,每当系统实际具有匹配实体时,它都知道可以对其进行处理。
但是,这使系统负责触发后续系统,因此很难对程序行为进行推理,因为单个系统交互不会导致错误的出现。添加新系统也变得更加困难,因为无法在不知道它们如何影响其他系统的情况下无法实施它们(并且可能必须修改先前的系统以触发新系统感兴趣的状态),这有点违反了拥有单独系统的目的一个任务。
这是我必须忍受的东西吗?我所看到的每个ECS示例都是实时的,并且很容易看到这种“每游戏一个迭代”循环在这种情况下的工作方式。而且我仍然需要它来进行渲染,这似乎真的不适合每次发生某些事情时都会暂停其大部分功能的系统。
是否存在一些适合于此的将游戏状态向前移动的设计模式,还是我应该将所有逻辑移出循环而仅在需要时才触发它?