Un singleton genérico
Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 43 de 64.
El singleton de la sección 3 son cinco líneas que repite cada administrador: un Instance estático, un Awake que lo establece y la comprobación de duplicados. Una clase base genérica las escribe una sola vez. Cada administrador deriva de ella y se nombra como el tipo:
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); }
}// en cualquier script
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");Un miembro estático de una clase genérica pertenece a cada tipo creado a partir de ella: Singleton<ScoreManager> y Singleton<SoundManager> son dos tipos, cada uno con su propio Instance, así que los administradores nunca comparten uno. ScoreManager.Instance ya tiene el tipo ScoreManager, que es para lo que sirve T. Dentro de la clase base, this solo se conoce como un Singleton<T>, así que this as T lo entrega como el administrador que realmente es.
La clase base es abstracta: Unity coloca solo los administradores en los objetos. Un administrador que necesite su propio Awake no debe escribir un void Awake() simple. Eso oculta el método de la clase base (el compilador lo advierte), Unity llama solo al del administrador y Instance nunca se establece. Anúlalo y llama primero al de la clase base:
protected override void Awake()
{
base.Awake();
score = 0;
}Desafío
IntermedioDales a ambos administradores una base que persista al cargar escenas.
- En
PersistentSingleton, escribeprotected virtual void Awake(): el primero se convierte enInstancey permanece (DontDestroyOnLoad); uno posterior se destruye a sí mismo. WalletyMusicPlayerheredan de esta clase; elimina suInstancey el Awake de Wallet.MusicPlayersobrescribe Awake:base.Awake()y, después, si es la Instance, registraNow playing: Adventure.
Pulsa «Jugar», visita el bosque y vuelve: 1 moneda. Después, pulsa «Comprobar».
Pruébalo tú mismo
using UnityEngine;
public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
// Awake: conserva el primero al cargar otras escenas y destruye cualquier instancia posterior
}
Todas las lecciones de Arquitectura de juegos en Unity
1Componentes, no jerarquías
Componentes pequeñosUn script base para enemigosComponentes abstractosComponentes que trabajan juntosRepaso: torreta modularRepaso: cañón doble4Datos serializados
Clases serializablesListas en el InspectorEnumeraciones en el InspectorRepaso: tabla de botínRepaso: sortear el botín2Interfaces en Unity
IDamageableInterfaces y TryGetComponentGetComponentsRepaso: Tecla de interacciónRepaso: El más cercano al alcance5ScriptableObjects
Activos de datosEstadísticas de armasConfiguración compartidaGuardar el vientoOleadas como datosRepaso: base de datos de objetosRepaso: comprar en la tienda8Código reutilizable
Métodos de extensiónUn singleton genéricoFunciones auxiliares genéricasRepaso: FindNearest3Eventos
Eventos de C# en UnitySuscribirse en OnEnableCampos UnityEventLos eventos controlan la interfazRepaso: ventana emergente de logrosRepaso: temporizador de la ventana emergentePractica por tu cuenta: Playground de Unity