Menu
CoddyTech

Mantenere i dati tra le scene

Fa parte della sezione Creare veri giochi del percorso Unity di Coddy. Lezione 20 di 60.

Il caricamento di una scena distrugge ogni oggetto della scena precedente, ma alcune cose devono durare per tutta la partita, come le monete che un giocatore porta da un livello all'altro. DontDestroyOnLoad(gameObject) sposta un oggetto fuori dalla sua scena e lo inserisce in una scena tutta sua, chiamata DontDestroyOnLoad nella Hierarchy quando si preme «Gioca», che i caricamenti non toccano mai. Funziona solo su un oggetto radice: su un oggetto figlio, Unity registra un avviso e non conserva nulla. Gli oggetti figli dell'oggetto conservato vengono mantenuti, ma non gli oggetti a cui punta: dopo il caricamento, un campo che puntava a un oggetto della vecchia scena contiene un oggetto distrutto, che risulta uguale 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);
    }
}

Questa GameSession si trova nella scena Menu. Si passa da Menu a Level1 e poi si torna a Menu, che ricrea tutti i suoi oggetti, compresa una nuova GameSession, mentre quella conservata è ancora presente. Senza il controllo in Awake ce ne sarebbero due e la nuova sostituirebbe Instance con 0 monete. Con il controllo, la nuova trova Instance già impostata, distrugge sé stessa e si ferma, mentre la sessione che ha attraversato i livelli rimane.

return è importante perché Destroy attende la fine del frame. Senza, il resto di Awake verrebbe comunque eseguito per la nuova istanza: Instance = this; farebbe puntare ogni script a un oggetto sul punto di essere distrutto.

challenge icon

Sfida

Facile

Mantieni attivo un unico cronometro della partita durante il caricamento di ogni scena.

  1. In Awake(), se Instance != null, chiama Destroy(gameObject); e return;. Altrimenti imposta Instance e chiama DontDestroyOnLoad(gameObject);.
  2. Il caricamento distrugge il testo del vecchio livello, quindi in Update(), prima della riga del testo, quando clockText == null, imposta clockText = GameObject.Find("ClockText").GetComponent<TMP_Text>();.

Premi «Gioca», vai a Level2 e torna indietro: un solo cronometro continua a contare. Poi premi «Verifica».

Provalo tu

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

Tutte le lezioni di Creare veri giochi

Esercitati da solo: Playground Unity