2011-09-07 12 views
6

estoy creando actualmente un juego de torre de defensa con C# & XNA. Los juegos funcionan bien y sin problemas durante un tiempo, pero después de jugar durante un buen período de tiempo (después de que suficientes enemigos/torres/balas han engendrado) el juego parece disminuir de forma exponencial. Incluso cuando se borran todas las instancias, el retraso persiste.La determinación de XNA Game Lag

Al principio pensé que esto podría tener que ver con la recolección de basura (y quizás sí) pero para probarlo escribí destructores para imprimir cuando se recolectó un objeto y todo se ve bien (se recogen todos los objetos). Entonces, tengo curiosidad si alguien tiene alguna experiencia con el retraso en XNA y las posibles causas de ello.

EDIT: Esto es para PC

+0

Sugerencia: Una mejor pregunta (general) podría ser -> ¿Qué puedo hacer yo para determinar dónde se produce el retraso? Parece que esto podría deberse a TANTAS cosas diferentes, tendríamos que ver mucho código para determinar la raíz del problema de retraso – jadarnel27

+0

Hay demasiado código para simplemente revisar. Estoy pidiendo más soluciones teóricas o posibles causas para lag. Actualmente no hay redes involucradas, por lo que no debería ser un problema. – Johannes

+1

Una cosa que sugeriría es imprimir (a un archivo de registro de depuración o algo así) una marca de tiempo al ingresar y salir de sus subrutinas/áreas de sospecha más grandes. De esta forma, puede ver dónde está perdiendo ese tiempo y trabajar hacia el problema – jadarnel27

Respuesta

0

¿Se ha aumentado el tiempo de bucle del juego? Agregue cronómetro al inicio y al final del ciclo de actualización y el bucle de dibujo. Si está aumentando, intente descartarlo (mueva el cronómetro.Inicio() y/o el cronómetro.Detenga()) hasta que encuentre cuál es la causa de la desaceleración. Si no aumenta, es causado por otra cosa.

tratar de añadir esta línea al código:

SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false)/1000 /* in kilobytes */, 
POSITION, Color.White, 0f); 

(DrawInt64/32 es una extensión muy útil para SpriteBatch que le permite dibujar los números sin generar basura, disponible aquí:. http://pastebin.com/pVw66mGy alternativa sólo tiene que utilizar cordón y .Encadenar()).

Everytime reduce el valor indicado, se corrió la recolección de basura.

+0

Una mejor forma de determinar si se están produciendo colecciones de basura es utilizar GC.CollectionCount(). Esto le permitirá ver cuándo se recopila cada generación individual. Las colecciones de Generación 0 probablemente no sean un gran problema; las colecciones de generación 1 y 2 son mucho más preocupantes cuando se trata de rendimiento. –

1

Si le preocupa que las recolecciones de basura tengan un impacto en el rendimiento, una de las mejores herramientas que puede aprender a usar es CLR Profiler. Esta utilidad le permite crear un perfil de las asignaciones de heap realizadas por su programa, de modo que pueda identificar qué métodos exactamente generan basura. Recuerde que muchas cosas no obvias pueden asignarse al montón: concatenando cadenas, indexando diccionarios con claves de enumeración, cierres, delegados, etc. Incluso un poco de basura, generada una vez por fotograma a más de 60 fotogramas por segundo, puede sumarse rápidamente bajo las circunstancias correctas.

Dicho esto, lo que has descrito no suena como un problema con la recolección de basura para mí. Por lo general, el GC es lo suficientemente rápido, incluso durante una recopilación completa, para que solo se eliminen algunos fotogramas; en otras palabras, notará un pequeño y molesto tirón de vez en cuando, pero no una desaceleración persistente.

(Advertencia: esto sólo se aplica en el PC, que tiene un GC muy sofisticado en comparación con otras plataformas de XNA.)

Usted debe tratar de conectar un generador de perfiles a su código para identificar qué métodos están tomando más tiempo para completar ; si su problema no está relacionado con GC, esto puede ser informativo. En el pasado, he usado EQATEC, aunque he tenido problemas con algunas de sus versiones más recientes. Puede intentarlo, o puede buscar en Google una alternativa.

0

No olvides desenganchar eventos, ¿verdad? en el siguiente ejemplo agrego 4 sprites a una lista, cada sprite engancha un evento del juego. Luego elimino un sprite y planteo el evento.

En esta situación, los 4 sprites aún están activos y su evento se debe a que todavía hay una referencia en Game.

solo un pensamiento, si estás utilizando eventos para tus objetos del juego, podrías dejarlos a todos quietos.

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"); 
     }  
    }