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;
}Défi
MoyenDonne aux deux gestionnaires une classe de base qui survit aux changements de scène.
- Dans
PersistentSingleton, écrisprotected virtual void Awake(): le premier devientInstanceet reste en place (DontDestroyOnLoad) ; un exemplaire ultérieur se détruit. WalletetMusicPlayeren héritent ; supprime leurInstanceet le Awake de Wallet.MusicPlayerredéfinit Awake :base.Awake(), puis, s’il s’agit de l’Instance, consigneNow 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
1Des composants, pas des hiérarchies
De petits composantsUn script de base pour les ennemisComposants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaireRécapitulatif : canon double4Données sérialisées
Classes sérialisablesListes dans l’InspecteurÉnumérations dans l’InspecteurRécapitulatif : table de butinRécapitulatif : tirer le butin2Les interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interactionLe plus proche à portée5ScriptableObjects
Ressources de donnéesStatistiques des armesParamètres partagésSauver le ventLes vagues comme donnéesRécapitulatif : base de données des objetsRécapitulatif : acheter dans la boutique8Code réutilisable
Méthodes d’extensionUn singleton génériqueFonctions utilitaires génériquesRécapitulatif : FindNearest3Événements
Les événements C# dans UnityS’abonner dans OnEnableChamps UnityEventLes événements pilotent l’interfaceRécapitulatif : fenêtre de succèsRécapitulatif : minuteur de la fenêtreEntraînez-vous par vous-même : Playground Unity