2011-09-07 107 views
6

我目前正在创建一个使用C的塔防游戏#& XNA。游戏运行良好,平稳一段时间,但玩了很长时间(足够的敌人/塔/子弹产生后),游戏似乎成倍减速。即使所有实例都被清除,滞后仍然存在。我开始以为这可能与垃圾收集有关(也许它的确如此),但为了测试它,我收集了一个对象并且一切看起来都很好(收集了所有对象)时编写了析构函数来打印。所以我很好奇,如果任何人有任何XNA滞后的经验和可能的原因呢?确定XNA游戏滞后

编辑:这是PC

+0

建议:一个更好的(总体)问题可能是 - >我能做些什么来确定滞后发生的地方?看起来这可能是由许多不同的事情引起的,我们必须看到很多代码才能确定滞后问题的根源 – jadarnel27

+0

有太多代码可以简单地查看。我更多地要求理论解决方案或可能的原因滞后。目前没有网络涉及,所以不应该是一个问题。 – Johannes

+1

我建议的一件事就是在进入和退出较大的子程序/怀疑区域时打印(到调试日志文件或其他内容)时间戳。通过这种方式,你可以看到你在哪里丢失了时间,并朝着这个问题前进 – jadarnel27

回答

0

游戏循环时间是否增加?将秒表添加到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())。

每当显示的数字减少时,就会运行垃圾收集。

+0

确定垃圾收集是否发生的更好方法是使用GC.CollectionCount()。这将允许您查看收集每一代的时间。第0代收集可能不是什么大问题;第一代和第二代系列在性能方面更受关注。 –

1

如果您担心垃圾收集会影响性能,您可以学习使用的最佳工具之一是CLR Profiler。该实用程序允许您分析程序执行的堆分配,以便您可以确定哪些方法正在生成垃圾。请记住,许多非显而易见的事情可以分配到堆上:连接字符串,使用枚举键索引字典,关闭,委托等。即使每帧以每秒60帧以上的速度产生一次垃圾,也可以快速累积在适当的情况下。

这就是说,你所描述的并不像听我说的垃圾回收问题。即使在完整的收集过程中,GC的速度通常也足够快,只会导致几帧丢失 - 换句话说,您会经常注意到一个次要的,令人讨厌的混蛋,但不会持续放缓。

(警告:这仅适用于个人电脑,相比其他XNA平台它有一个非常复杂的GC上。)

你应该尝试分析器连接到你的代码,以确定哪些方法耗时最长完成;如果你的问题与GC无关,这可能是有益的。在过去,我使用EQATEC,虽然我有一些更新版本的问题。你可以试试这个,或者你可以在Google上寻找替代方案。

0

你不会忘记解除事件吗?在下面的示例中,我将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"); 
     }  
    }