top of page
Foto del escritorBraulio Madrid

Un Singleton que te salva la vida


En esta ocasión haré un pequeño script útil que me ha servido para todo. la fuente era de la página de tomodomo.org, pero no te preocupes porque ya no existe la pagina y aqui estoy para rescatarte.


Últimamente estoy volviendo a un viejo proyecto que dejé abandonado, un pequeño demo que se hizo para la Global Game Jam que se celebró en Medellín hace unos años, no era la gran cosa, pero el estrés era enorme, volví a revisar la demo poco a poco, paso a paso y encontre desde todo tipo de malas prácticas de codificación, hasta assets redundantes, pesima animacion. Si logro que todo salga bien, entonces publicaré tanto el viejo demo como el nuevo por un tiempo, la idea es comparar como se vé la evolución de ambos.


Que es un singleton


Singleton es un patrón de diseño de software que permite llamar a una única instancia de un objeto en lugar de estar creando varios objetos de algo que debería ser único. Un ejemplo cuando creas un Game Manager, que suelen ser scripts que manejan todo lo que ocurre dentro de una escena y entonces piensas, para qué quieres dos managers, sería igual que dos cocineros trabajando en un mismo plato o para que querrias controlar 2 o 3 o 20 personajes con un mismo Joystick, por eso, este patrón está para evitar que algún error produzca duplicidad de cosas y solo llame a un objeto único.


En unity un singleton cualquiera debe cumplir con 3 condiciones:

  • Debe servir para cualquier clase que desee convertirse en singleton.

  • Debe garantizar la no duplicidad de objetos al ser llamados por otras clases.

  • Debe permitir elegir si ser persistente entre escenas o no.


Y para que sea funcional opino que debería ser:

  • Ser sencillo de entender

  • Ser sencillo de implementar y de invocar

  • No romperse durante los cambios de versión de unity.


Vamos a crear una nueva script en C# de unity con el nombre singleton, una ves dentro vamos a borrar la función Start y Update.


Lo primero, cualquier clase debe poderse convertir en singleton. Para lograr esto hay que hacer que nuestra clase herede de monobehaviour y ponerle una variable de tipo <T>, donde la T será cualquier clase o componente que nosotros deseemos que herede de singleton.

public class Singleton<T>:MonoBehaviour where T: Component

Segundo, hay que hacer que se garantice que solo habrá un objeto de ese tipo en toda la escena, para hacerlo debemos hacer una variable Estática que sea del tipo de Componente que deseamos, pero que esté bloqueada a ser llamada del exterior así sin mas.

public static T Instance {get; private set;}

Lo que queremos prevenir es que algun script pueda sobreescribir el objeto con cualquier otra cosa, ahora procedemos a hacer la comprobación de si el componente de la instancia es el único.


public virtual void Awake()
{
    if(Instance == null)
    {
        Instance = this as T;
    }
    else
    {
        Destroy(gameObject);
    }
}

Por último debe garantizarse que será persistente o no, para eso solo le agregamos una línea después de Instance = this as T


Instance = this as T;
DontDestroyOnLoad(this);

Listo, eso ha sido todo, he usado esta implementación por que al ser mas simple, no requerir librerias raras, perdura mas entre versiones de unity y es fácil de entender siempre.


using UnityEngine;

public class Singleton<T> : MonoBehaviour where T: Component
{
    public static T Instance { get; private set; }
    public virtual void Awake()
    {
        if (Instance == null)
        {
            Instance = this as T;
            DontDestroyOnLoad(this);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

Ahora solo queda explicar la implementación. Si quieres hacer que tu clase se convierta en singleton, solo debes hacer que herede de Singleton en lugar de monobehaviour y como parámetro enviar la misma clase como tipo.

public class Clase:Singleton<Clase>{}

Si desea instanciarla, solo necesitaria crear una variable y luego llamarla en start.

private Clase clase;

void Start()
{
    clase = Clase.Instance;
}

Esto es todo por esta ocasión, espero que le saques partido, siempre lo que es simple es más funcional.


Hasta otra 😁

14 visualizaciones0 comentarios

Comments


bottom of page