我目前正在创建一个使用C的塔防游戏#& XNA。游戏运行良好,平稳一段时间,但玩了很长时间(足够的敌人/塔/子弹产生后),游戏似乎成倍减速。即使所有实例都被清除,滞后仍然存在。我开始以为这可能与垃圾收集有关(也许它的确如此),但为了测试它,我收集了一个对象并且一切看起来都很好(收集了所有对象)时编写了析构函数来打印。所以我很好奇,如果任何人有任何XNA滞后的经验和可能的原因呢?确定XNA游戏滞后
编辑:这是PC
我目前正在创建一个使用C的塔防游戏#& XNA。游戏运行良好,平稳一段时间,但玩了很长时间(足够的敌人/塔/子弹产生后),游戏似乎成倍减速。即使所有实例都被清除,滞后仍然存在。我开始以为这可能与垃圾收集有关(也许它的确如此),但为了测试它,我收集了一个对象并且一切看起来都很好(收集了所有对象)时编写了析构函数来打印。所以我很好奇,如果任何人有任何XNA滞后的经验和可能的原因呢?确定XNA游戏滞后
编辑:这是PC
有,我用退房性能两件事情。
1)应用程序中心有一个Performance utility,你可以用它来帮助确定你有什么改进。
2)现在有点老了,但是for the Xbox 360 this document helped me a lot。
更新:我也忘了this Gamefest 2010 presentation。它也有几件事情。
游戏循环时间是否增加?将秒表添加到Update循环和Draw循环的开始和结束处。如果它正在增加,请尝试排除(移动stopwatch.Start()和/或stopwatch.Stop()),直到找到导致减速的原因。如果不增加,则是由其他原因造成的。
尝试将此行添加到代码:
SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false)/1000 /* in kilobytes */,
POSITION, Color.White, 0f);
(DrawInt64/32是spritebatch真正有用的扩展,它允许您在不产生垃圾得出的数字,可以在这里找到:http://pastebin.com/pVw66mGy或者只是使用束带和.ToString())。
每当显示的数字减少时,就会运行垃圾收集。
确定垃圾收集是否发生的更好方法是使用GC.CollectionCount()。这将允许您查看收集每一代的时间。第0代收集可能不是什么大问题;第一代和第二代系列在性能方面更受关注。 –
如果您担心垃圾收集会影响性能,您可以学习使用的最佳工具之一是CLR Profiler。该实用程序允许您分析程序执行的堆分配,以便您可以确定哪些方法正在生成垃圾。请记住,许多非显而易见的事情可以分配到堆上:连接字符串,使用枚举键索引字典,关闭,委托等。即使每帧以每秒60帧以上的速度产生一次垃圾,也可以快速累积在适当的情况下。
这就是说,你所描述的并不像听我说的垃圾回收问题。即使在完整的收集过程中,GC的速度通常也足够快,只会导致几帧丢失 - 换句话说,您会经常注意到一个次要的,令人讨厌的混蛋,但不会持续放缓。
(警告:这仅适用于个人电脑,相比其他XNA平台它有一个非常复杂的GC上。)
你应该尝试分析器连接到你的代码,以确定哪些方法耗时最长完成;如果你的问题与GC无关,这可能是有益的。在过去,我使用EQATEC,虽然我有一些更新版本的问题。你可以试试这个,或者你可以在Google上寻找替代方案。
你不会忘记解除事件吗?在下面的示例中,我将4个精灵添加到列表中,每个精灵都会挂钩游戏中的事件。然后,我删除一个精灵,并提出事件。
在这种情况下,所有4个精灵仍然活跃,并获得他们的事件,因为在游戏中仍然有对他们的引用。
只是一个念头,如果你正在使用你的游戏对象的事件,你可能会让它们全部继续运行。
class Game
{
public event EventHandler SomeEvent;
List<Sprite> sprites;
public Game()
{
sprites = new List<Sprite>();
sprites.Add(new Sprite(this));
sprites.Add(new Sprite(this));
sprites.Add(new Sprite(this));
sprites.Add(new Sprite(this));
sprites.RemoveAt(0);
EventHandler temp = SomeEvent;
if (temp != null)
{
temp(this, EventArgs.Empty);
}
}
static void Main(string[] args)
{
Game newProgram = new Game();
}
class Sprite
{
public Sprite(Game gameReference)
{
gameReference.SomeEvent += new EventHandler(gameReference_SomeEvent);
}
void gameReference_SomeEvent(object sender, EventArgs e)
{
Debug.WriteLine("Event");
}
}
建议:一个更好的(总体)问题可能是 - >我能做些什么来确定滞后发生的地方?看起来这可能是由许多不同的事情引起的,我们必须看到很多代码才能确定滞后问题的根源 – jadarnel27
有太多代码可以简单地查看。我更多地要求理论解决方案或可能的原因滞后。目前没有网络涉及,所以不应该是一个问题。 – Johannes
我建议的一件事就是在进入和退出较大的子程序/怀疑区域时打印(到调试日志文件或其他内容)时间戳。通过这种方式,你可以看到你在哪里丢失了时间,并朝着这个问题前进 – jadarnel27