Unity Singleton Manager classes

Dans Unity, quel est le bon moyen de créer un gestionnaire de jeu singleton accessible partout en tant que classe globale avec des variables statiques qui cracheront les mêmes valeurs constantes dans chaque classe qui extrait ces valeurs? Et quel serait le moyen de le mettre en œuvre dans Unity? Dois-je l’attacher à un GameObject? Peut-il simplement être là dans un dossier sans être visuellement dans la scène?

Comme toujours: ça dépend. J’utilise des singletons des deux types, des composants attachés à GameObject et des classes autonomes non dérivées de MonoBehaviour . OMI, la question générale est de savoir comment les instances sont liées au cycle de vie de scènes, d’objects de jeu, … Et pour ne pas oublier parfois, il est plus pratique d’avoir un composant faisant particulièrement référence à d’autres objects MonoBehaviour est plus sûr et plus sûr.

  1. Certaines classes doivent simplement fournir certaines valeurs, comme par exemple une classe de configuration qui doit charger les parameters de la couche de persistance lorsqu’elle est appelée. Je conçois ces cours comme de simples singletons.
  2. D’autre part, certains objects doivent savoir quand une scène est démarrée, c’est-à-dire que Start est appelé ou doivent effectuer des actions dans Update ou d’autres méthodes. Ensuite, je les implémente en tant que composant et les attache à un object de jeu survivant lors du chargement de nouvelles scènes.

J’ai conçu des singletons basés sur des composants (type 2) avec deux parties: un GameObject persistant appelé Main , qui contient tous les composants, et un singleton plat (type 1) appelé MainComponentManager pour sa gestion. Un code de démonstration:

 public class MainComponentManger { private static MainComponentManger instance; public static void CreateInstance () { if (instance == null) { instance = new MainComponentManger (); GameObject go = GameObject.Find ("Main"); if (go == null) { go = new GameObject ("Main"); instance.main = go; // important: make game object persistent: Object.DontDestroyOnLoad (go); } // sortinggger instantiation of other singletons Component c = MenuManager.SharedInstance; // ... } } GameObject main; public static MainComponentManger SharedInstance { get { if (instance == null) { CreateInstance (); } return instance; } } public static T AddMainComponent  () where T : UnityEngine.Component { T t = SharedInstance.main.GetComponent (); if (t != null) { return t; } return SharedInstance.main.AddComponent  (); } 

Maintenant, les autres singletons qui veulent s’inscrire en tant que composant Main ressemblent à ceci:

 public class AudioManager : MonoBehaviour { private static AudioManager instance = null; public static AudioManager SharedInstance { get { if (instance == null) { instance = MainComponentManger.AddMainComponent (); } return instance; } } 

Les ingénieurs qui débutent dans Unity ne le remarquent souvent pas.

vous ne pouvez pas avoir un “singleton” dans un système ECS.

Cela n’a pas de sens.

Tout ce que vous avez dans Unity, c’est GameObjects, aux positions XYZ. Ils peuvent avoir des composants attachés.

Ce serait comme essayer d’avoir “un singleton” ou un “inheritance” dans … Photoshop ou Microsoft Word.

Fichier Photoshop – pixels aux positions XY
Fichier d’ éditeur de texte – lettres aux positions X
Fichier Unity – GameObjects aux positions XYZ

C’est “aussi simple que cela”.

De toute façon, vous devez absolument avoir une scène de précharge dans chaque projet Unity.

Incroyablement simple comment faire: https://stackoverflow.com/a/35891919/294884

C’est si simple, c’est un non-problème.

Une fois qu’Unity aura inclus une “scène de préchargement intégrée” (c’est-à-dire, pour vous sauver d’un clic et en créer un), cela ne sera finalement plus jamais discuté.

(Remarque A – certains des langages que vous utilisez pour comstackr Components for Unity ont bien sûr des concepts OO; Unity lui-même n’a aucun lien avec OO.)

(Remarque B: dans les premiers jours d’Unity, vous voyiez des tentatives de création de code qui “crée un object de jeu à la volée – et le maintient unique – et s’y attache” . En plus d’être bizarre, FWIW n’est théoriquement pas Il est également possible d’assurer l’unicité (même pas dans un cadre). Là encore, c’est tout à fait théorique, car c’est un non-problème sortingvial, dans Unity, les comportements généraux s’inscrivent dans la scène du préchargement.)

Si cette classe sert uniquement à accéder à des variables globales, vous n’avez pas vraiment besoin d’un modèle singleton, ni d’un object GameObject.

Créez simplement une classe avec des membres statiques publics.

 public class Globals { public static int mStatic1 = 0; public static float mStatic2 = 0.0f; // ....etc } 

Les autres solutions sont correctes mais excessives si tout ce dont vous avez besoin est un access global aux variables.

J’ai écrit une classe singleton qui facilite la création d’objects singleton. C’est un script MonoBehaviour, vous pouvez donc utiliser les Coroutines. Son basé sur cet article de wiki de Unity , et j’appendai l’option pour le créer à partir de Prefab plus tard.

Donc, vous n’avez pas besoin d’écrire les codes Singleton. Il suffit de télécharger cette classe de base Singleton.cs , de l’append à votre projet et de créer votre singleton en l’étendant:

 public class MySingleton : Singleton { protected MySingleton () {} // Protect the constructor! public ssortingng globalVar; void Awake () { Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID()); } } 

Maintenant, votre classe MySingleton est un singleton, et vous pouvez l’appeler par instance:

 MySingleton.Instance.globalVar = "A"; Debug.Log ("globalVar: " + MySingleton.Instance.globalVar); 

Voici un tutoriel complet: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/

C’est la configuration que j’ai créée.

Commencez par créer ce script:

MonoBehaviourUtility.cs

 using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; static public class MonoBehaviourUtility { static public T GetManager( ref T manager ) where T : MonoBehaviour { if (manager == null) { manager = (T)GameObject.FindObjectOfType( typeof( T ) ); if (manager == null) { GameObject gameObject = new GameObject( typeof( T ).ToSsortingng() ); manager = (T)gameObject.AddComponent( typeof( T ) ); } } return manager; } } 

Dans n’importe quelle classe, vous voulez être un singleton, procédez comme suit:

 public class ExampleManager : MonoBehaviour { static public ExampleManager sharedManager { get { return MonoBehaviourUtility.GetManager( ref _sharedManager ); } } static private ExampleManager _sharedManager; } 

Une façon de le faire est de faire une scène juste pour initialiser votre gestionnaire de jeu comme ceci:

 public class GameManager : MonoBehaviour { GameManager static instance; //other codes void Awake() { DontDestroyOnLoad(transform.gameObject); instance = this; } //other codes } 

C’est tout, c’est tout ce que vous devez faire. Et puis immédiatement après l’initialisation du gestionnaire de jeu, chargez la scène suivante et ne revenez plus jamais sur cette scène.

Consultez ce tutoriel: https://youtu.be/64uOVmQ5R1k?list=WL