管理大量对象

时间:2011-01-26 13:29:50

标签: c#

我正在编写自己的游戏,处理大量游戏实体(数量约为1000)。 必须在屏幕上绘制每个实体。一开始我不确定C#会给我一个很好的帧率。但是,当我应用一些基本的剔除时,我对更高的帧速率感到震惊。

所以现在,当我向实体添加AI逻辑时,每个对象的更新时间都需要一些时间。我有对象的列表,我通过它们循环并调用obj.Update(dt)。看起来这种方式不是最好的。 “巨大”实体的更新可能需要很多ms,所以其他人需要等待那个人完成自己的更新。

所以我的问题是:在管理大量动态对象时哪种方式更好?

3 个答案:

答案 0 :(得分:3)

您遇到的问题是您正在遍历调用Update方法的对象。如果没有更新什么怎么办?如果每个框架都不需要需要更新怎么办?

最好在主循环中添加一个事件,让对象订阅它:

public void FrameListener(float _ticks);


public class Game
{
    public Event FrameListener OnFrame;
}

现在,每当需要更新任何内容时,它只会订阅此事件(获取传递给它的delta-tick计数)。当一个对象变为空闲时,它可以取消订阅自己。使用此方法,只有需要更新的对象才会更新。

此外,您可以在订阅过程中添加一个计数器(意味着您可能会抛弃事件对象而支持AddListener()类型方法),告诉系统只能在每个'n'帧中调用委托。例如,在你可能有建筑生产的游戏中(定居者,文明等),这些东西在每一帧都更新他们的生产是没有意义的。即使每5秒就足够了。当你可以准确定义对象需要更新的频率时,这会减少许多开销。

静态对象永远不会灌输委托,所以永远不会造成任何开销。

答案 1 :(得分:3)

首先,1000个对象实际上不是巨大的。在60 fps时,每个对象的60 kHz,即16μs - 大多数硬件上至少32,000个时钟周期。有些物品必须付出高昂的代价。

假设您不能降低每个对象的成本,您可以为更新对象分配总时间预算,并在该时间过去时停止循环,但保持从下一帧的相同位置循环,环绕如果你到达终点时还有更多的时间,那么就开始了。简而言之,在环形缓冲区周围运行,每当时间用完时停止渲染帧。

答案 2 :(得分:1)

我认为你的问题与游戏开发无关,而与一般表演原则有关。

您可能需要探索优化性能的多种方法。这是列表,但并非详尽无遗:

  • 多线程/并行:可以实现非常好的改进,但会在您的应用程序中增加很多复杂性。如果您使用c#4,则可以查看新的并行库
  • 根据VS的版本和版本,您可以激活代码分析(如果在VS中不可用,则使用FXcop)。该工具可以提供良好的建议
  • 使用分析工具来发现代码的瓶颈
  • 使用工具分析代码的复杂性,尤其是圈复杂度
  • google了解一般性能提示(字符串生成器VS字符串连接等)
  • 谷歌更多的硬编码性能提示(改变方法中的参数顺序,减少值变量的使用,减少调用图等)。

更具体游戏开发的提示(来自我承认的游戏开发新手): *尝试在子集而不是单个集合中对对象进行分区...有时候更高效的是拥有对象图,而不是对象列表。您可以更新图形的单个节点而不是整个对象 *如果可能更新未显示的对象,则排除