对于我正在制作的 2D 游戏(对于 Android),我使用的是基于组件的系统,其中 GameObject 包含多个 GameComponent 对象。GameComponents 可以是诸如输入组件、渲染组件、子弹发射组件等。目前,GameComponents 拥有对拥有它们的对象的引用并可以对其进行修改,但 GameObject 本身只有一个组件列表,它并不关心组件是什么,只要在对象更新时可以更新它们即可。
有时一个组件有一些 GameObject 需要知道的信息。例如,对于碰撞检测,游戏对象向碰撞检测子系统注册自己,以便在它与另一个对象碰撞时得到通知。碰撞检测子系统需要知道对象的边界框。我将 x 和 y 直接存储在对象中(因为它被多个组件使用),但宽度和高度只有保存对象位图的渲染组件才知道。我想在 GameObject 中有一个方法 getBoundingBox 或 getWidth 来获取该信息。或者一般来说,我想将一些信息从组件发送到对象。但是,在我当前的设计中,GameObject 不知道它在列表中有哪些特定组件。
我可以想到几种方法来解决这个问题:
我可以让 GameObject 拥有一些重要组件的特定字段,而不是拥有一个完全通用的组件列表。例如,它可以有一个名为renderingComponent的成员变量;每当我需要获取我刚刚使用的对象的宽度时
renderingComponent.getWidth()
。该解决方案仍然允许通用组件列表,但它对其中一些组件的处理方式不同,而且我担心我最终会拥有几个异常字段,因为需要查询更多组件。有些对象甚至没有渲染组件。将所需信息作为 GameObject 的成员,但允许组件对其进行更新。因此,对象的宽度和高度默认为 0 或 -1,但渲染组件可以在其更新循环中将它们设置为正确的值。这感觉像是一种 hack,为了方便起见,我最终可能会将许多东西推送到 GameObject 类,即使并非所有对象都需要它们。
让组件实现一个接口,该接口指示它们可以查询的信息类型。例如,渲染组件将实现 HasSize 接口,该接口包括 getWidth 和 getHeight 等方法。当 GameObject 需要宽度时,它会遍历其组件,检查它们是否实现了 HasSize 接口(
instanceof
在 Java 或is
C# 中使用关键字)。这似乎是一种更通用的解决方案,一个缺点是搜索组件可能需要一些时间(但是,大多数对象只有 3 或 4 个组件)。
这个问题不是关于特定问题的。它经常出现在我的设计中,我想知道处理它的最佳方法是什么。因为这是一个游戏,所以性能有点重要,但每个对象的组件数量通常很少(最多为 8 个)。
短版
在基于组件的游戏系统中,在保持设计通用性的同时将信息从组件传递到对象的最佳方式是什么?