昨天,我阅读了GDC Canada上有关属性/行为实体系统的演示,我认为它很棒。但是,我不确定如何实践地使用它,而不仅仅是理论上的。首先,我将快速向您解释该系统的工作方式。
每个游戏实体(游戏对象)都由属性(=数据,可以通过行为,也可以通过“外部代码”访问)和行为(=逻辑,包含OnUpdate()
和OnMessage()
)组成。因此,例如,在Breakout克隆中,每个积木将由(例如!)组成:PositionAttribute,ColorAttribute,HealthAttribute,RenderableBehaviour,HitBehaviour。最后一个看起来像这样(这只是一个用C#编写的无效示例):
void OnMessage(Message m)
{
if (m is CollisionMessage) // CollisionMessage is inherited from Message
{
Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith
if (otherEntity.Type = EntityType.Ball) // Collided with ball
{
int brickHealth = GetAttribute<int>(Attribute.Health); // owner's attribute
brickHealth -= otherEntity.GetAttribute<int>(Attribute.DamageImpact);
SetAttribute<int>(Attribute.Health, brickHealth); // owner's attribute
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
else if (m is AttributeChangedMessage) // Some attribute has been changed 'externally'
{
if (m.Attribute == Attribute.Health)
{
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
}
如果您对此系统感兴趣,可以在此处(.ppt)阅读更多内容。
我的问题与该系统有关,但通常与每个基于组件的实体系统有关。我从未见过任何这些在真实的计算机游戏中如何真正发挥作用,因为我找不到任何好的例子,如果找到一个例子,就没有记载,也没有评论,所以我听不懂。
那么,我想问什么?如何设计行为(组件)。我在GameDev SE上已经读到,最常见的错误是制造许多组件,而只是“使所有组件成为组件”。我已经读到,建议不要在组件中进行渲染,而要在组件外部进行渲染(因此,代替RenderableBehaviour,它应该是RenderableAttribute,并且如果实体的RenderableAttribute设置为true,则Renderer
(与组件,但引擎本身)应该在屏幕上绘制它?)。
但是,行为/组件如何?比方说,我有一个级别,并在级别,有一个Entity button
,Entity doors
和Entity player
。当玩家与按钮碰撞时(这是一个按压力切换的地板按钮),将其按下。按下按钮后,它将打开门。好吧,现在该怎么做?
我想出了这样的东西:玩家拥有CollisionBehaviour,它检查玩家是否与某物发生碰撞。如果他有一个按钮碰撞,它会发送CollisionMessage
到button
实体。该消息将包含所有必要的信息:谁与按钮碰撞。该按钮具有ToggleableBehaviour,它将收到CollisionMessage
。它会检查与谁发生了碰撞,并且该实体的权重是否足以切换按钮,按钮是否会被切换。现在,它将按钮的ToggledAttribute设置为true。好吧,但是现在呢?
该按钮是否应该向其他所有对象发送另一条消息,以告诉他们该消息已被切换?我认为,如果我做这样的一切,我将收到成千上万条消息,并且会变得非常混乱。所以这也许更好:门不断检查链接到它们的按钮是否被按下,并相应地更改其OpenedAttribute。但这意味着门的OnUpdate()
方法将不断地做某事(这真的有问题吗?)。
第二个问题:如果我有更多种类的按钮该怎么办。一种是通过压力按压,另一种是通过枪击来切换,第三种是在往其上注水时进行切换,依此类推。这意味着我将不得不具有不同的行为,如下所示:
Behaviour -> ToggleableBehaviour -> ToggleOnPressureBehaviour
-> ToggleOnShotBehaviour
-> ToggleOnWaterBehaviour
这是真实游戏的运作方式还是我只是愚蠢?也许我只有一个ToggleableBehaviour,它会根据ButtonTypeAttribute表现。因此,如果它是a ButtonType.Pressure
,则执行此操作;如果它是a ButtonType.Shot
,则执行其他操作...
那我想要什么?我想问一下我是否做得对,或者我只是愚蠢而我不了解组件的要点。我没有找到任何有关组件在游戏中如何真正发挥作用的好例子,仅发现了一些教程描述了如何制作组件系统,但没有介绍如何使用它。