Menu
CoddyTech

Un singleton générique

Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 43 sur 64.

Le singleton de la section 3 se résume à cinq lignes que chaque gestionnaire répète : un Instance statique, un Awake qui le définit, et la vérification des doublons. Une classe de base générique les écrit une seule fois. Chaque gestionnaire en hérite en se désignant lui-même comme type :

public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    protected virtual void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this as T;
    }
}

public class ScoreManager : Singleton<ScoreManager>
{
    public int score;
    public void Add(int points) { score += points; }
}

public class SoundManager : Singleton<SoundManager>
{
    public void Play(string clip) { Debug.Log("Playing " + clip); }
}
// dans n’importe quel script
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");

Un membre statique d’une classe générique appartient à chaque type créé à partir de celle-ci : Singleton<ScoreManager> et Singleton<SoundManager> sont deux types qui possèdent chacun un Instance ; les gestionnaires ne partagent donc jamais le même. ScoreManager.Instance est déjà typé ScoreManager, et c’est à cela que sert T. Dans la classe de base, this n’est connu que comme un Singleton<T> ; this as T le transmet donc sous la forme du gestionnaire qu’il est réellement.

La classe de base est abstraite : Unity place uniquement les gestionnaires sur les objets. Un gestionnaire qui a besoin de son propre Awake ne doit pas écrire un simple void Awake(). Cela masque la méthode de la classe de base (le compilateur vous avertit), Unity n’appelle alors que celle du gestionnaire et Instance n’est jamais défini. Redéfinissez-la et appelez d’abord la méthode de la classe de base :

protected override void Awake()
{
    base.Awake();
    score = 0;
}
challenge icon

Défi

Moyen

Donne aux deux gestionnaires une classe de base qui survit aux changements de scène.

  1. Dans PersistentSingleton, écris protected virtual void Awake() : le premier devient Instance et reste en place (DontDestroyOnLoad) ; un exemplaire ultérieur se détruit.
  2. Wallet et MusicPlayer en héritent ; supprime leur Instance et le Awake de Wallet.
  3. MusicPlayer redéfinit Awake : base.Awake(), puis, s’il s’agit de l’Instance, consigne Now playing: Adventure.

Appuie sur « Jouer », visite la forêt et reviens : 1 pièce. Puis appuie sur « Vérifier ».

Essayez vous-même

using UnityEngine;

public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    // Awake : conserver la première instance lors des chargements de scènes, détruire toute instance créée ensuite
}

Toutes les leçons de Architecture de jeu dans Unity

Entraînez-vous par vous-même : Playground Unity