我正在编写自己的游戏,处理大量游戏实体(数量约为1000)。 必须在屏幕上绘制每个实体。一开始我不确定C#会给我一个很好的帧率。但是,当我应用一些基本的剔除时,我对更高的帧速率感到震惊。
所以现在,当我向实体添加AI逻辑时,每个对象的更新时间都需要一些时间。我有对象的列表,我通过它们循环并调用obj.Update(dt)。看起来这种方式不是最好的。 “巨大”实体的更新可能需要很多ms,所以其他人需要等待那个人完成自己的更新。
所以我的问题是:在管理大量动态对象时哪种方式更好?
答案 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)
我认为你的问题与游戏开发无关,而与一般表演原则有关。
您可能需要探索优化性能的多种方法。这是列表,但并非详尽无遗:
更具体游戏开发的提示(来自我承认的游戏开发新手): *尝试在子集而不是单个集合中对对象进行分区...有时候更高效的是拥有对象图,而不是对象列表。您可以更新图形的单个节点而不是整个对象 *如果可能更新未显示的对象,则排除