Un singleton générique
Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 34 sur 50.
Le singleton de la section 3 consiste en 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 dérive en se désignant 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 ont chacun leur Instance, donc les gestionnaires ne partagent jamais la 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>, donc this as T le transmet sous la forme du gestionnaire qu'il est réellement.
La classe de base est abstraite : Unity ne place que 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 émet un avertissement), Unity n'appelle que celle du gestionnaire, et Instance n'est jamais défini. Remplacez la méthode et appelez d'abord celle de la classe de base :
protected override void Awake()
{
base.Awake();
score = 0;
}Défi
MoyenUne ville et une forêt, reliées par des portails violets. Chaque scène possède son propre objet Wallet et MusicPlayer, si bien que l’un ou l’autre joue de son côté, et les pièces appellent Wallet.Instance.Add(1). Aujourd’hui, chaque gestionnaire est le singleton de la section 3 : à chaque chargement, le portefeuille est remplacé par un portefeuille vide. Donne aux deux gestionnaires une classe de base générique qui les conserve lors des chargements de scène :
- Dans
PersistentSingleton.cs, écrispublic abstract class PersistentSingleton<T>, un MonoBehaviour pour n’importe quel type MonoBehaviour T, avec une propriété statique publiqueInstancede type T que seule la classe peut définir, et une méthodeprotected virtual void Awake(). - Son Awake conserve la première instance de son type : celle-ci devient Instance et survit aux chargements de scène. Toute instance ultérieure détruit son propre objet et ne change rien d’autre.
WalletetMusicPlayeren héritent, et leurs propres champsInstancedisparaissent.MusicPlayerconserve son propre Awake, qui afficheNow playing: Adventuredans les journaux. Il doit s’exécuter après l’Awake de la classe de base, et uniquement pour l’instance qui reste, afin que la musique démarre une seule fois par partie.
Les flèches déplacent le Player. Appuie sur Play, ramasse la pièce, va dans la forêt puis reviens, et enfin appuie sur Check.
Essayez vous-même
using UnityEngine;
// PersistentSingleton<T> : une instance qui persiste lors des chargements de scènes
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Architecture de jeu dans Unity
1Des composants, pas des hiérarchies
Des composants simplesUn script de base pour les ennemisDes composants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaire4Données sérialisées
Classes sérialisablesListes dans l’inspecteurÉnumérations dans l’inspecteurRécapitulatif : table de butin7Machines à états
Les états sous forme de classesUne machine à étatsTransitionsLes cerveaux des ennemisRécapitulatif : états d’une porte10Projet : Survivant de l’arène
Le hérosTypes d’ennemis2Interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interaction5ScriptableObjects
Assets de donnéesStatistiques des armesParamètres partagésLes vagues sous forme de donnéesRécapitulatif : base de données d’objets8Code réutilisable
Méthodes d’extensionUn singleton génériqueFonctions utilitaires génériquesRécapitulatif : FindNearest