Menu
CoddyTech

Conserver entre les scènes

Fait partie de la section Créer de vrais jeux du Journey Unity de Coddy. Leçon 20 sur 56.

Le chargement d’une scène détruit tous les objets de l’ancienne, mais certaines choses doivent durer pendant toute la partie, comme les pièces qu’un joueur emporte d’un niveau à l’autre. DontDestroyOnLoad(gameObject) déplace un objet hors de sa scène, dans une scène qui lui est propre, appelée DontDestroyOnLoad dans la fenêtre Hierarchy pendant le mode Play, que les chargements ne touchent jamais. Cela ne fonctionne que sur un objet racine : sur un enfant, Unity affiche un avertissement et ne conserve rien. Les enfants de l’objet conservé l’accompagnent, mais pas les objets vers lesquels il ne fait que pointer : après le chargement, un champ qui pointait vers un objet de l’ancienne scène contient un objet détruit, qui est considéré comme égal à null.

public class GameSession : MonoBehaviour
{
    public static GameSession Instance;
    public int coins;

    void Awake()
    {
        if (Instance != null)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

Cette GameSession se trouve dans la scène Menu. Le déroulement est Menu, Level1, puis retour à Menu, et Menu recrée tous ses objets, y compris une nouvelle GameSession, alors que celle qui a été conservée est toujours là. Sans la vérification dans Awake, il y en aurait deux, et la nouvelle remplacerait Instance avec 0 pièce. Avec cette vérification, la nouvelle trouve Instance déjà définie, se détruit et s’arrête, et la session qui a traversé les niveaux reste en place.

return est important, car Destroy attend la fin de la frame. Sans lui, le reste de Awake s’exécuterait quand même pour la nouvelle instance : Instance = this; ferait pointer tous les scripts vers un objet sur le point d’être détruit.

challenge icon

Défi

Facile

Un chronomètre de speedrun. L’objet RunClock dans Level1 compte les secondes de toute la partie et enregistre un temps intermédiaire chaque fois qu’un niveau est terminé. Le Goal doré de Level1 charge Level2, dont le goal charge à nouveau Level1, et chaque goal appelle d’abord RunClock.Instance.Split(). Chaque niveau a son propre HUD avec un ClockText ; dans l’Inspector, on attribue au RunClock celui de Level1. Les flèches déplacent le Player. Modifie RunClock.cs afin que :

  • le chronomètre continue de tourner lors du chargement de chaque scène, sans repartir de zéro ;
  • le temps s’affiche toujours dans le ClockText du niveau ouvert, sous la forme Time: 12.3 ;
  • en revenant à Level1, qui possède son propre RunClock, il n’y ait toujours qu’un seul chronomètre, celui qui tourne déjà, et que RunClock.Instance soit celui-ci.

Appuie sur Play, va dans Level2 puis reviens, et termine à nouveau Level1, puis clique sur Check.

Essayez vous-même

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

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Créer de vrais jeux