12

我已经有 10 年没有编程游戏了(我的最后一次经历是 DJGPP + Allegro),但我想我会在周末去看看 XNA 看看它是如何形成的。

我印象深刻,但是当我继续拼凑游戏引擎时,我有一个(可能)基本问题。

您应该在多大程度上依赖 C# 的委托和事件来推动游戏?作为一名应用程序程序员,我大量使用委托和事件,但我不知道这样做是否有很大的开销。

在我的游戏引擎中,我设计了一种“追逐凸轮”,可以附加到对象上,然后重新计算其相对于对象的位置。当物体移动时,有两种方法可以更新追踪凸轮。

  • 在主游戏循环中有一个“UpdateCameras()”方法。
  • 使用事件处理程序,并让追踪摄像头订阅 object.OnMoved。

我使用后者,因为它允许我将事件链接在一起并很好地自动化引擎的大部分。突然间,巨大而复杂的东西被降到了少数 3 到 5 行事件处理程序中……真是太棒了。

但是,如果每纳秒触发一次的事件处理程序会导致严重的减速,我将删除它并使用循环方法。

想法?

4

7 回答 7

10

如果您将事件视为订阅者列表,那么在您的代码中您所做的就是注册订阅者。在 CLR 级别,实现这一目标所需的指令数量可能最少。

如果您希望您的代码是通用的或动态的,那么您需要在调用事件之前检查是否订阅了某些内容。C# 和 .NET 的事件/委托机制以极低的成本(就 CPU 而言)为您提供了这一点。

如果您真的关心每个时钟周期,那么您永远不会编写通用/动态游戏逻辑。这是可维护/可配置代码和完全速度之间的权衡。

写得好,在我能证明这是一个问题之前,我会支持活动/代表。

您真正知道这对您来说是否是个问题的唯一方法是分析您的代码——无论如何,对于任何游戏开发,您都应该这样做!

于 2008-09-15T15:41:23.603 回答
4

重要的是要意识到 C# 中的事件不是排队的异步事件(例如,Windows 消息队列)。它们本质上是一个函数指针列表。因此,引发事件不会比遍历函数指针列表并调用每个指针对性能产生更糟糕的影响。

同时,意识到正因为如此,事件是同步的。如果您的事件侦听器很慢,您将减慢引发事件的类。

于 2008-09-15T19:19:09.917 回答
2

这里的主要问题似乎是:“使用 C# 委托和事件相关的开销是多少?”

与常规函数调用相比,事件几乎没有显着的开销。

使用委托可以创建隐含的因此隐藏的垃圾。垃圾可能是导致性能问题的主要原因,尤其是在 Xbox360 上。

以下代码以 EntityVisitor 对象的形式每秒生成大约 2000 字节的垃圾(以 60 fps 的速度):

    private delegate void SpacialItemVisitor(ISpacialItem item);

    protected override void Update(GameTime gameTime)
    {
        m_quadTree.Visit(ref explosionCircle, ApplyExplosionEffects);
    }

    private void ApplyExplosionEffects(ISpacialItem item)
    {
    }

只要您避免产生垃圾,委托就足以满足大多数目的。因为存在隐患,我宁愿避开它们,改用接口。

于 2008-09-17T04:09:39.880 回答
1

XNA 鼓励使用接口、事件和委托来驱动用它编写的东西。查看为您设置的 GameComponent 相关类。

答案是“只要你觉得舒服就行”。

详细说明一下,例如,如果您从 gamecomponent 类继承并继承到 cameracontroller 类,并将其添加到 Game.Component 集合中。然后您可以创建您的相机类并将它们添加到您的相机控制器。

这样做会导致相机控制器被定期调用,并且能够选择和激活正确的相机或多个相机,如果这是你想要的。

这是一个例子(他所有的教程都很棒): ReoCode

于 2008-09-15T15:41:27.787 回答
1

在我远离实际工作的额外时间里,我也一直在学习 XNA。

恕我直言(或者如果您问我的同事,请不要那么谦虚)是事件句柄的开销将被游戏中的其他元素(例如渲染)压倒。鉴于在正常的 .Net 编程中大量使用事件,我认为底层代码已经得到了很好的优化。

老实说,我认为使用 UpdateCameras 方法可能是过早的优化。除了相机之外,事件系统可能还有更多用途。

于 2008-09-15T15:42:28.640 回答
1

顺便说一句,您可能有兴趣知道Allegro的原始开发人员Shawn Hargreaves是 XNA 团队的主要开发人员之一 :-)

于 2008-09-15T20:56:30.120 回答
1

在了解事件对性能的影响之前,您必须首先评估是否需要它。

假设您确实在尝试更新追踪摄像头并且它不仅仅是一个示例,那么您正在寻找的不是一个事件(尽管事件也可能起到作用),如果您正在关注一个化身,那么它可能是大部分时间都在移动。

我发现一种非常有效的方法是使用分层转换,如果您有效地实现这一点,相机将不会是唯一受益于这样一个系统的对象,目标是将相机保持在对象的坐标空间内追踪。

如果您想对相机跟踪对象的速度和方式应用一些弹性,那么这种方法并不是最好的方法,为此,最好使用更新调用、参考以及一些基本的加速度和阻力物理。

Events are more useful for things that only happen from time to time or that affect many different aspects of the application, like a character dying, probably many different systems would like to be aware of such an event, kill statistics, the controlling AI, and so on, in such a case, keeping track of all the objects that would be have to constantly check if this has happened is far less effective than throwing an event and having all the interested objects be notified only when it happens.

于 2012-05-28T23:17:39.743 回答