2009-09-21 16 views
9

Actualmente estoy trabajando en un juego de plataformas Flash muy grande (cientos de clases) y estoy lidiando con un problema donde el juego se detiene lentamente si lo dejas el tiempo suficiente. No escribí el juego, así que solo estoy vagamente familiarizado con sus aspectos internos. Algunos de los misteriosos síntomas incluyen,AS3 gran degradación del rendimiento del juego en el tiempo

  • El juego funcionará bien durante un tiempo determinado (en un nivel determinado) cuando, de repente, se iniciará una fuga de memoria de forma exponencial.
  • El tiempo que demora el juego en llegar al punto donde se produce una fuga exponencial es más corto cuando hay más sprites en la pantalla.
  • Incluso cuando no se muestra nada visiblemente en la pantalla, el juego se ralentiza.
  • El juego se ralentiza más rápido con colisiones de sprites más frecuentes.
  • Inhabilitar por completo el código de colisión ralentiza la degradación, pero no impide que el juego caiga eventualmente.

Mirando a la fuente y el uso de Flex perfilador, mis primeros sospechosos son,

  • hay muchos objetos vagancia, especialmente WeakMethodClosure, tomando grandes cantidades de memoria.
  • El programa hace un uso extremadamente extenso de oyentes de eventos débiles (docenas enviados por cuadro).
  • BitmapData se está copiando cada vez que se crea un nuevo sprite. Estos son sprites de 50x50 píxeles que generan alrededor de 8 sprites por segundo.

Sé que es casi imposible decirme el problema sin ver la fuente, por lo que estoy buscando datos que puedan ayudarme a reducir esto. ¿Alguien ha experimentado esta evasiva degradación del rendimiento en sus propios proyectos? ¿Cuál fue la causa en tu caso?

Respuesta

7

Recientemente completé una optimización de un proyecto grande. Y te puedo dar algunos consejos arquitectónicos:

  1. principio principal - Pruebe hacer lo menos posible la función/eventos llamadas
  2. deshacerse de todos ellos, salvo uno onEnterFrame/onInterval/OnTimer ciclos. Haga todo lo que necesita en una llamada al evento general. Probablemente necesitará muchas matrices estáticas para almacenar referencias de objetos procesados ​​ .
  3. ¿Sus gráficos/render cosas también en uno bucle principal
  4. uso
  5. Try grandes (probablemente) prerendered lienzos en lugar de pequeños sprites/mapas de bits. Por lo general, se puede utilizar para fondos. Pero también trabaja bien para un objetos más pequeños (como árboles, plataformas, etc.)
  6. deshacerse fuera pequeños recursos de mapa de bits, ensamblarlo a una sola hoja de baldosas y sacar sus cosas directamente de ella, a través de propiedad de origen-rect

Espero que te ayude! Fugas de memoria, por ejemplo, headash.

P.S. Pon a prueba tu juego en diferentes navegadores, es decir, la mayoría de los que pierden, a veces no borra la memoria después de cada actualización.

+0

Creo que este es un gran consejo para alguien que acaba de comenzar un gran proyecto de juego y se pregunta cómo estructurarlo mejor. – Kai

0

Parece que necesita un perfil de su aplicación para ver qué está sucediendo.

Este hilo tenía un par de sugerencias, pero, en última instancia, tendrá que poner simplemente el código para ayudar a determinar qué está pasando.

Profiling ActionScript-3 Code

Es posible que desee para ver si sólo se puede ejecutar algunas partes más pequeñas durante un período de tiempo y ver si ve una desaceleración.

Es posible que desee probar la unidad de su aplicación, por lo que puede ejecutar varias partes rápidamente, buscando fugas de memoria. Un marco es: http://asunit.org/, y otro es: prueba http://opensource.adobe.com/wiki/display/flexunit/

unidad es algo que utilizo una gran cantidad de perfiles, por lo que se puede probar en el nivel superior de su juego, ejecutarlo miles de veces, en busca de problemas, luego ejecute cada parte y vea cuál tiene problemas, y solo avance hacia abajo. Este es un proceso manual, pero si las dos ideas en el hilo de SO enumeradas al principio no ayudan, este puede ser su mejor enfoque.

¿Está utilizando demasiada memoria? ¿O su uso de la CPU es demasiado alto?

+0

La pregunta menciona fugas de memoria, así que supongo que el uso de la CPU no es el problema. –

+0

Estoy tratando de ver si hay otros problemas además de lo que está adivinando. Lamentablemente, cuando he adivinado dónde mis programas tienen problemas, tiendo a equivocarme, y por eso dependo tanto de los perfiles. –

+0

Me pregunto si la recolección excesiva de basura conduce a una degradación del programa, debido a que se generan demasiados objetos demasiado rápido. –

0

Primero determine si se trata de un límite de memoria o procesador al que está golpeando.Suena como el último, parece que hay muchos objetos haciendo cosas por ahí ... probablemente esos sprites extra no estén siendo liberados bien. Busque dependencias entre objetos/variables/cualquier cosa en esos eventos, asegúrese de que los sprites se eliminen, preste atención a cualquier controlador de EnterFrame o eventos recurrentes.

3
  • Evite los métodos anónimos - cámbielos a métodos de nivel de clase.
  • Uso referencia débil en addEventListener y/o asegúrese de eliminar todos los oyentes de un objeto antes de extraerla con removeChild
  • Asegúrese de que todos los sprites removeChild en lugar de limitarse a dejar que vuelen fuera de la pantalla. Además, si es posible, reutilice los sprites en lugar de crear nuevos.
1

Debería considerar la agrupación de objetos si tiene mucha creación/destrucción, especialmente con objetos pesados ​​como bitmapdata.

ver Object Pool class

+0

Esta es una gran idea una vez que identifico qué recursos están causando el cuello de botella. – Kai

0

Suena mucho más probable que llegan al límite de la velocidad del procesador de memoria. Tienes que probar con una tapa extra de memoria una aplicación Flash.

Afortunadamente, hay un montón de cosas fáciles que puede hacer para mantener la CPU abajo ...

1) gestionar con severidad detectores de eventos para todo , especialmente los oyentes de ratón. ¿Tienes oyentes de eventos $ texas en todos tus objetos sprite? Eso podría ser un problema.

2) Acceda a las matrices utilizando int u uint en lugar de Number. Esto es enorme, y este es uno de esos trucos de Adobe remansados. El acceso al objeto array con int y uint es mucho más rápido que Number y si realiza muchas iteraciones (y suena como lo hace) esto podría restar milisegundos a la ejecución de su marco.

3) En la misma línea que el n. ° 2, supervise sus operaciones matemáticas y los tipos que está utilizando para ciertas operaciones. Lo más lento que puede hacer en operaciones matemáticas para AS3 es la conversión repetitiva (alimentar ints a una función que devuelve un Número), o realizar operaciones básicas como sumar y restar en Número en lugar de int.

Lo bueno de tener un programa de wtfhuge como este en Flash es que incluso un pequeño cambio de optimización podría tener un gran impacto en el rendimiento. Una vez jugué con un motor de trazado de rayos en AS3 donde declare una variable adicional y mató mi FPS de 30 a 23.

+0

Estoy seguro de que mi juego está rompiendo estas reglas en al menos algunos lugares. ¡Espero que sea tan fácil como eso! – Kai

0
Flash tiene un problema bastante infame (muchos lo consideran un error) que hace que los detectores de eventos para los temporizadores y el evento ENTER_FRAME no se recojan basura, incluso si fueron referenciados débilmente. Por lo tanto, aunque es una buena práctica usar eventos a los que se hace referencia débilmente, aún así debería eliminar todos los detectores de eventos cuando ya no sean necesarios.
+0

Después de una búsqueda rápida de Event.ENTER_FRAME, he encontrado 18 coincidencias, por lo que es seguro decir que el problema podría estar aquí también. – Kai

Cuestiones relacionadas