List <T> .AddRange导致短暂延迟

Jus*_*les 3 c# xna profiling list

我有一个实现ICollidable接口的实体列表.此接口用于解决实体之间的冲突.因此我的实体是:

  • 玩家
  • 敌人
  • 项目
  • 瓷砖

在每次游戏更新(大约60 t/s)时,我正在清除列表并根据游戏状态添加当前实体.我通过以下方式完成此任务:

collidableEntities.Clear();
collidableEntities.AddRange(players);
collidableEntities.AddRange(enemies);
collidableEntities.AddRange(projectiles);
collidableEntities.AddRange(items);
collidableEntities.AddRange(camera.VisibleTiles);
Run Code Online (Sandbox Code Playgroud)

一切正常,直到我将可见的瓷砖添加到列表中.运行游戏循环的前1-2秒会导致可见的打嗝延迟绘制(因此我可以看到渲染中的抖动).我可以逐字地删除/添加添加切片的行,看看是否发生抖动,所以我将其缩小到该行.

我的问题是,为什么?VisibleTiles列表大约有450-500个磁贴,因此实际上并没有那么多数据.每个图块包含Texture2D(图像)和Vector2(位置),以确定渲染的内容和位置.我要继续寻找,但是从我的头顶,我无法理解为什么只有前1-2秒打嗝然后从那里开始顺利.

任何建议表示赞赏.

更新

我已经尝试将初始容量增加到大约元素量,但没有观察到差异.

更新

根据要求,这是camera.VisibleTiles的代码

public List<Tile>
{
    get { return this.visibleTiles; }
}
Run Code Online (Sandbox Code Playgroud)

Col*_*ell 5

每当遇到这样的性能问题时,正确的反应就是不要猜测可能的原因是什么; 正确的答案是分析应用程序.有很多选择; 我相信你可以在StackOverflow上找到建议.

但是,我今天感觉很幸运,所以我会忽略我刚才给你的建议,并采取疯狂的猜测.我将解释我的推理,我希望将来有助于诊断这些问题.

事实上,你所描述的问题只发生一次,而且只在游戏开始时才让我相信它不是列表本身或碰撞逻辑的功能所固有的.当然,这假设列表中的对象数量在这段时间内基本上是恒定的.如果它由其中任何一个引起的,我希望它会在每一帧都发生.

因此我怀疑垃圾收集器.您可能会在游戏开始时看到GC正在发生 - 换句话说,就在您将所有大量资产加载到内存中之后.您也可能会在代码中看似随机的点上看到它,因为您分配的任何对象理论上都可以将它从边缘推送到集合中.

我的猜测是这样的:当您加载游戏时,您创建的资产会产生大量的收集压力,但仍不足以触发收集.当您在游戏过程中分配对象时(在这种情况下,由于调整列表大小),它会将收集压力增加到GC最终决定激活的点,从而导致您观察到的抖动.一旦GC运行,并且所有适当的对象都已降级为正确的几代,抖动就会停止.

正如我所说,这只是一个猜测,虽然是一个受过教育的人.但是,测试很简单.GC.Collect(2)在进入渲染循环之前添加一个调用.如果我是对的,抖动应该消失.

如果你想要比这更彻底 - 我强烈推荐它 - 微软提供了一个对调试内存问题很有用的工具,CLR Profiler.此工具将准确显示收集何时发生以及原因.它对XNA开发非常有用.