juegos - unity ios build
Unity3d Trabajar con memoria: cargar y descargar prefabricados (2)
¡Realmente necesito ayuda! No puedo entender cómo trabajar con prefabs y descarga.
Tengo la siguiente situación.
Ejecuto mi aplicación en IPad desde Xcode. Unity versión 4.3.1 Pro. Mire la memoria usando: Xcode Debug Navigator Xcode Instruments Unity Profiler
Hago los siguientes pasos:
0) La unidad comienza desde la escena vacía.
Memoria usada XCODE Debug Navigator: 11 mb Instrumentos: 26.4 mb Unity Profiler: total utilizado 13.2 reservado total 13.7
1) Cargar prefabricadas de la carpeta de Recursos
prefab = Resources.Load("Room1");
Memoria utilizada XCODE Debug Navigator: 30.8 mb Instrumentos: 49.54 mb Unity Profiler: total utilizado 19.8 reservado total 20.4
2) Instancia prefabricada
go = (GameObject)Instantiate(prefab);
go.name = "Room1";
XCODE Debug Navigator: 31.2 mb Instrumentos: 50 mb Unity Profiler: total utilizado 20 reservado total 20.7
3) Destruye todos los objetos en la escena - memoria no cambiada
Transform[] tr = FindObjectsOfType<Transform>();
for (int i = 0; i < tr.Length; i++)
{
GameObject goo = tr.gameObject;
if (goo.name != "Main Camera")
{
Destroy(goo);
goo = null;
}
}
XCODE Debug Navigator: 31.1 mb Instrumentos: 49.93 mb Unity Profiler: total utilizado 19.8 total reservado 20.4
4) Resources.UnloadUnusedAssets();
- memoria no cambiada
5) Llamar a System.GC.Collect();
- memoria no cambiada
6) Llamar a UnloadAsset de prefab Resources.UnloadAsset(prefab);
- memoria no cambiada
7) Resources.UnloadUnusedAssets();
- memoria parcialmente limpiada
XCODE Debug Navigator: 21.9 mb Instrumentos: 40.79 mb Unity Profiler: total usado 13.2 total reservado 13.9
En Profiler veo que eliminó todas las texures, que se usaban en prefabricadas
8) System.GC.Collect();
- memoria no cambiada
9) Cargar escena vacía - memoria no modificada
Aquí hay otro momento interesante:
Cuando la aplicación se pone en segundo plano y comienzo otra aplicación, el tamaño de la RAM utilizada disminuye mucho, y cuando llamo a la aplicación de unidad, la memoria va al primer tamaño con la escena vacía.
Tengo las siguientes preguntas:
1) ¿Por qué la memoria no se ha limpiado completamente después de eliminar prefabricados y llamar a UnloadUnusedAssets? Podemos verlo en Instruments y Xcode, pero en Profiler vemos que esa memoria es prácticamente gratuita.
2) ¿Es real limpiar la memoria al tamaño inicial?
3) ¿Todos pasos bien o hago algo mal?
Puede descargar el proyecto de prueba aquí: http://gfile.ru/aa5on
Muchas gracias por tus respuestas.
Preámbulo
Es bueno que conozcas el uso de RAM. Pero, la pregunta es: ¿has encontrado algún problema con el uso de la memoria hasta el momento? Si no, entonces lo que haces es prematuro.
Algunos pensamientos
Aquí hay algunos pensamientos para que considere:
- Artículo importante para leer: http://docs.unity3d.com/Manual/MobileProfiling.html
- Hay memoria Unity y memoria mono. Mono nunca devolverá memoria al sistema operativo:
Una vez que asigna una cierta cantidad de memoria, está reservada para mono y no está disponible para el sistema operativo. Incluso cuando lo libere, estará disponible internamente solo para Mono y no para el sistema operativo. El valor de la memoria del montón en el Analizador solo aumentará, nunca disminuirá.
- Las prefabricadas y los objetos de juego son solo un montón de enlaces, por lo que no tienen una huella de memoria tan grande como los recursos.
Object.Destroy
no destruye el objeto al instante :La destrucción real del objeto siempre se retrasa hasta después del bucle actual de actualización, pero siempre se realizará antes del procesamiento.
-
Resources.UnloadUnusedAssets
es asincrónico. No descarga todo al instante. - No se menciona en los documentos de Unity que
Resources.UnloadAsset(Object assetToUnload)
descargará los recursos a los que hace referenciaassetToUnload
.
Explicación
No puedo llamarme un experto en gestión de memoria (de Unity y Mono). Pero así es como entiendo lo que está pasando:
1) Cargar prefabricadas de la carpeta de Recursos
Prefab se cargó con todos los recursos a los que hace referencia. El uso de memoria aumentó. Todo está claro ahora.
2) Instancia prefabricada
El uso de la memoria aumentó un poco para mantener el clon prefabricado.
3) Destruye todos los objetos en la escena - memoria no cambiada
Aquí vienen cosas interesantes :) En realidad, el uso de la memoria ha cambiado de acuerdo con el generador de perfiles de Unity: es el mismo que antes de la instanciación de prefabricados. Entonces, parece que Unity ha lanzado algo que estaba directamente relacionado con la instancia prefabricada. Pero, como se dice, mono no devolverá la memoria al sistema operativo (y ni siquiera es el momento para hacerlo, incluso si lo hiciera).
4) Recursos de llamada.UnloadUnusedAssets (); - memoria no cambiada
Resources.UnloadUnusedAssets
no descarga nada aquí, porque todavía no hay activos no utilizados: aunque los objetos fueron marcados para su destrucción, la recolección de basura real no ha tenido lugar.5) Llamar a System.GC.Collect (); - memoria no cambiada
Es porque es memoria administrada por mono.
6) Llamar a UnloadAsset de prefab Resources.UnloadAsset (prefab);
Creo que el uso de la memoria se ha reducido un poco aquí (100K-200K más o menos) pero no lo has notado. Pero, como he mencionado anteriormente,
UnloadAsset
no descargará los recursos a los que hace referencia el objeto queUnloadAsset
como parámetro aUnloadAsset
.7) Recursos de llamada.UnloadUnusedAssets (); - memoria parcialmente limpiada
En el paso 5 ha invocado GC.Collect (), se ha producido la recopilación y ahora algunos de los activos de Unity no tienen referencias sobre ellos. Por lo tanto, pueden ser liberados finalmente. Es por eso que la memoria ha sido liberada.
8) System.GC.Collect (); - memoria no cambiada
Explicado arriba
9) Cargar escena vacía - memoria no modificada
Todo lo que podría ser liberado ya ha sido liberado. Por lo tanto, no hay cambio en el uso de la memoria.
Bueno, tal vez necesito ver el problema desde otro lado: ¿limpiar la memoria cuando la aplicación Unity está en pausa? Tal vez alguien sabe, ¿cómo hacerlo? O reinícielo cuando intento iniciar la aplicación en pausa.