Conservar entre escenas
Parte de la sección Creación de juegos reales del Journey de Unity de Coddy. Lección 20 de 60.
Cargar una escena destruye todos los objetos de la anterior, pero algunas cosas deben durar toda la partida, como las monedas que un jugador lleva de un nivel a otro. DontDestroyOnLoad(gameObject) saca un objeto de su escena y lo coloca en una escena propia, llamada DontDestroyOnLoad en la Jerarquía al pulsar «Jugar», que las cargas nunca afectan. Solo funciona con un objeto raíz: si se aplica a un objeto secundario, Unity registra una advertencia y no conserva nada. Los objetos secundarios del objeto conservado también se mantienen, pero no los objetos a los que solo apunta: después de la carga, un campo que apuntaba a un objeto de la escena anterior contiene un objeto destruido, que se compara como igual a null.
public class GameSession : MonoBehaviour
{
public static GameSession Instance;
public int coins;
void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
}Esta GameSession está en la escena Menu. Al pulsar «Jugar», se pasa de Menu a Level1 y después se vuelve a Menu, que vuelve a crear todos sus objetos, incluida una nueva GameSession, mientras la que se conservó sigue allí. Sin la comprobación en Awake habría dos, y la nueva reemplazaría Instance con 0 monedas. Con ella, la nueva encuentra que Instance ya está asignada, se destruye y se detiene, y la sesión que pasó por los niveles permanece.
return es importante porque Destroy espera hasta el final del fotograma. Sin él, el resto de Awake seguiría ejecutándose para la nueva: Instance = this; haría que todos los scripts apuntaran a un objeto a punto de ser destruido.
Desafío
FácilMantén un único reloj de la partida durante la carga de todas las escenas.
- En
Awake(), siInstance != null, llama aDestroy(gameObject);y areturn;. De lo contrario, estableceInstancey llama aDontDestroyOnLoad(gameObject);. - La carga destruye el texto del nivel anterior, así que en
Update(), antes de la línea del texto, cuandoclockText == null, establececlockText = GameObject.Find("ClockText").GetComponent<TMP_Text>();.
Pulsa «Jugar», ve a Level2 y vuelve: un único reloj sigue contando. Después, pulsa «Comprobar».
Pruébalo tú mismo
using UnityEngine;
using TMPro;
public class RunClock : MonoBehaviour
{
public static RunClock Instance;
public TMP_Text clockText;
private float seconds;
void Awake()
{
Instance = this;
}
void Update()
{
seconds += Time.deltaTime;
clockText.text = "Time: " + seconds.ToString("0.0");
}
public void Split()
{
Debug.Log("Split: " + seconds.ToString("0.0"));
}
}
Todas las lecciones de Creación de juegos reales
1Texto en pantalla
Canvas y textoMuestra la puntuaciónDa formato a los númerosUn temporizador de cuenta regresivaRepaso: velocímetro4Escenas y niveles
Cargar una escenaReiniciar el nivelSiguiente nivelConservar entre escenasRepaso: selección de nivel2Botones y pantallas
Botones y onClickLambdasConectar en el InspectorPaneles activados y desactivadosBarras de saludRepaso: tienda de mejoras5Guardar con PlayerPrefs
Guardar un númeroCargar con un valor predeterminadoPuntuación más altaGuardar ajustesRepaso: monedas en el banco3El gestor del juego
Un solo script ejecuta el juegoEl SingletonEstados del juegoActivar el estadoRepaso: gestor de rondas6Proyecto: Corredor sin fin
Tres carrilesObstáculos por delante9El nuevo sistema de entrada
Dos sistemas de entradaTeclado y ratónPulsado en este fotogramaAcciones de entradaRepaso: cambio de entradaPractica por tu cuenta: Playground de Unity