Al igual que en las solicitudes http, donde no existe persistencia entre cada solicitud, uno de los problemas que tenemos cuando estamos desarrollando una aplicación o juego en Unity 3D es la persistencia de información entre el cambio de escenas o levels.
1 |
Application.LoadLevel("miescena"); |
En Unity, al cargar un nuevo nivel, todos los objetos en la escena se destruyen y a continuación se cargan los objetos en el nuevo nivel. Por tanto, las variables que teníamos en el nivel pierden sus referencias y valores, siendo imposible recuperar la información que tenían en la escena nueva cargada.
A menudo, necesitamos pasar información de una escena a otra, por ejemplo cuantas monedas tenía el usuario en la pantalla anterior o ciertos parámetros de configuración que no queremos que se pierdan durante este cambio.
Unity dispone en su API de la llamada “DontDestroyOnLoad(target)” (Unity reference to DontDestroyOnLoad()). Este método hace que el objeto “target” no sea destruido automáticamente al cargar una nueva escena, pudiendo preservar el objeto durante la carga. Si el objeto “target” es un component o game object, entonces su jerarquía completa no será destruida.
Como es un poco “coñazo” ir haciendo esta llamada en todas las escenas, os propongo una solución para crearos un gestor de objetos persistentes.
Para ello primer crearemos una clase Singleton que será la encargada de gestionar las llamadas a DontDestroyOnLoad a todos los objetos que hereden de él en al escena. Os pongo el sencillo código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using UnityEngine; using System.Collections; public class Singleton<T> : MonoBehaviour where T : Singleton<T> { protected static Singleton<T> mInstance { get { if (!_mInstance) { T[] managers = GameObject.FindSceneObjectsOfType(typeof(T)) as T[]; if (managers.Length != 0) { if (managers.Length == 1) { _mInstance = managers[0]; _mInstance.gameObject.name = typeof(T).Name; return _mInstance; } else { Debug.LogError("You have more than one " + typeof(T).Name + " in the scene. You only need 1, it's a singleton!"); foreach (T manager in managers) { Destroy(manager.gameObject); } } } GameObject gO = new GameObject(typeof(T).Name, typeof(T)); _mInstance = gO.GetComponent<T>(); DontDestroyOnLoad(gO); } return _mInstance; } set { _mInstance = value as T; } } private static T _mInstance; } |
Posteriormente, si por ejemplo quisiéramos crear una clase que fuera “ProjectVars.cs”, en el que almacenar diferentes parametros de configuración, simplemente hay que heredar de la clase “Singleton<T>” y crear una variable que devuelva la instancia que permita esa persistencia.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections.Generic; using UnityEngine; public class ProjectVars : Singleton<ProjectVars> { /// <summary> /// Este string estara activo entre escenas /// </summary> public string StringActiveBetweenScenes; public static ProjectVars Instance { get { return ((ProjectVars)mInstance); } set { mInstance = value; } } protected ProjectVars() { } } |
Y para hacerle referencia en cualquier parte de nuestras escenas:
1 2 3 4 |
void SomeFunction () { ProjectVars.Instance.StringActiveBetweenScenes = "test var"; var test = ProjectVars.Instance.StringActiveBetweenScenes; } |
Ahora ya disponemos de un gestor de variables persistentes entre escenas en Unity.
Os dejo los archivos para añadir directamente a vuestro proyecto:
Descargar archivos de persistencia entre escenas en Unity
Javi Giner
Latest posts by Javi Giner (see all)
- IIS Express Visual Studio, como configurar para permitir conexiones remotas - febrero 26, 2016
- Evento solidario sobre Innovación - diciembre 14, 2015
- Uso de Component en Unity - noviembre 10, 2015
Muy interesante tu solución para la persistencia de variables! Muy útil y elegante 😉 Gracias por el aporte! Estaré pendiente de tus publicaciones.
Por si te resulta útil, en mi blog también tengo algunos posts sobre recursos de programación en Unity 😉
Saludos!
Gracias Santi,
Me parece muy interesante tu blog, y muy completo. Dejo la url para quien le interese:
https://histeriagamedev.wordpress.com
Tienes un nuevo seguidor, a ver si entre todos hacemos una buena comunidad de Unity
Gracias Javi!! Un placer!! 🙂