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