Cuando se trabaja con Unity, muchas veces hacer un buen uso de Awake y Start puede ser suficiente como “orden de ejecución” para manejar la inicialización de los sistemas. Por ejemplo, se puede usar Awake para asegurarse de que las referencias locales estén conectadas y luego usar Start para manejar cualquier inicialización coordinada o retrasada que pueda ser necesaria. Esta lección trata realmente sobre lo que se debe hacer cuando esos dos puntos de entrada no son suficientes.
Patrones de Unity
Para comenzar, veremos algunas soluciones específicas de los scripts MonoBehaviour.
Orden de ejecución del script
Creemos un proyecto de muestra para ilustrar algunas ideas. Comienza por crear un proyecto vacío: puedes usar cualquier plantilla, pero yo elegí una opción estándar de 2D Core. Abra la escena de muestra y cree un GameObject vacío. Luego, cree y adjunte instancias de cuatro clases nuevas que debe crear:
using UnityEngine;
public class SistemaDatos : MonoBehaviour
{
void Start() Debug.Log(this.GetType().Name);
}
using UnityEngine;
public class SistemaJuego : MonoBehaviour
{
void Start() Debug.Log(this.GetType().Name);
}
using UnityEngine;
public class SistemaControles : MonoBehaviour
{
void Start() Debug.Log(this.GetType().Name);
}
using UnityEngine;
public class SistemaRed : MonoBehaviour
{
void Start() Debug.Log(this.GetType().Name);
}
Estos cuatro scripts hacen lo mismo: utilizan el método Start como una oportunidad para inicializarse. En esta demostración sencilla, todo lo que eso significa es que imprimen su nombre en la consola para que podamos ver el orden en que se ejecutaron. Sin embargo, tenga en cuenta que REPRESENTAN la idea de un proyecto más completo y, por lo tanto, complejo.
Reproduce la escena y observa el orden en que la ves. En una de las ejecuciones vi:
1 - SistemaRed
2 - SistemaControles
3 - SistemaJuego
4 - SistemaDatos
Cabe destacar que este es el orden opuesto al que los agregué al GameObject. Tal vez pensaste que se reproducirían en el orden en que los agregaste, pero no creo que Unity haga ninguna promesa con respecto al orden en que se invocan los métodos MonoBehaviour de diferentes instancias de script. Supongo que probablemente tenga algo que ver con la serialización: tal vez los datos se guarden de una manera no ordenada como lo haría un diccionario.
Si estoy en lo cierto, entonces tendría sentido que Unity agregue una herramienta especial para manejar el “Orden de ejecución del script”.
Debería ver que ya se agregaron varios sistemas existentes y que se especificaron sus órdenes. Cuanto menor sea el número, antes se realizará la orden. Por ejemplo, UnityEngine.EventSystems.EventSystem , que tiene una orden de -1000
, se “iniciaría” antes de que UnityEngine.UI.ToggleGroup, ya que este último tiene una orden de 10
.
En este momento, nuestros cuatro sistemas tienen un orden de “Tiempo predeterminado” de “0”. Eso significa que se activarán después de “EventSystem” y antes de “ToggleGroup”. Si bien es posible asignar manualmente un orden a cada una de las clases, no recomiendo ese enfoque. En cambio, buscaría sistemas específicos que realmente necesiten activarse antes que otros sistemas, o que necesiten activarse después de otros sistemas y solo especificaría nuevos valores para esos casos especiales.
Supongamos que queremos que SistemaDatos se ejecute antes que SistemaJuego. Esto podría deberse a que queremos cargar los datos del juego antes de que el juego necesite trabajar con ellos. Desafortunadamente, en nuestro ejemplo anterior, SistemaJuego se ejecutó primero; ¡pensaría que el usuario no tenía datos guardados! 😄 Utilice la herramienta “Orden de ejecución de script” para solucionarlo:
1 - Haga clic en el botón más para agregar una nueva entrada
2 - Seleccione SistemaDatos de la lista que aparece
3 - Asignar un valor negativo al orden: quizás -10
4 - Haga clic en “Aplicar” y luego cierre la ventana.
Ejecute la escena nuevamente y observe el nuevo orden que aparece:
1 - SistemaDatos
2 - SistemaRed
3 - SistemaControles
4 - SistemaDatos
¡Perfecto! No me importaba el orden de los sistemas, excepto que quería que DataSystem se ejecutara primero, y ahora lo hizo. Esto sería así independientemente del orden de los componentes en un GameObject, o incluso si los scripts se distribuyeran entre varios GameObjects.