Menú
Gratis
Registro
hogar  /  Consejos/ Qué eventos existen en la unidad. Mis notas

¿Cuáles son los eventos en la unidad. Mis notas

Doy la bienvenida a todos. Hoy quiero hablar sobre cómo puedes implementar eventos de juego, presentarlos y también cómo hacer un sistema de eventos de juego completamente aceptable en Unity en dos clics sin recurrir a diferentes UnityAction.

Nota R: Este artículo no es la verdad de las verdades. Esta es solo mi idea y mi experiencia.

no hay tiempo para hacer fotos para el artículo, ¡pero es necesario! Por lo tanto, la imagen de Google!

Déjame darte un ejemplo con un ascensor. ¿Qué sabemos de él? Puede moverse hacia arriba o hacia abajo dependiendo del botón que se presione. Sin embargo, vale la pena recordar
que también abre/cierra puertas, reproduce un sonido y tal vez algo más. Durante mucho tiempo he estado acostumbrado a considerar muchas cosas en abstracto,
entonces puedo decir que los eventos del juego se pueden dividir en dos componentes. El primero es Manejadores. El segundo son los eventos.
Los controladores son scripts que desencadenan eventos del juego. Divido la convocatoria de eventos en varias opciones:

  1. Lineal. Esta opción significa que se ejecuta N” número de eventos después del siguiente.
  2. Paralelo. Generar más de un evento en el mismo controlador.
  3. Mezclado . Esta es una mezcla de la primera y la segunda opción.

Volvamos al ascensor. Inmediatamente puede decir que el ascensor se refiere a la opción número 3. Dejame explicar. Cuando presionamos el botón, se dispara el evento de movimiento del elevador. Además, cuando él está en su piso, las puertas se abren y, digamos, se reproduce un sonido. La apertura de las puertas y el sonido se producen en paralelo, pero después del movimiento. Inmediatamente puedes imaginar esto en la implementación del juego. Pero despues.

Para que os hagáis una idea de lo que entiendo por handlers, aquí tenéis algunos ejemplos: Triggers, botones pulsados ​​(teclas del teclado), beams (Raycast), etc.
Bueno, debajo de los gatillos: reproducir sonidos, mover objetos, etc.

En resumen, creé la siguiente arquitectura:

Parece bastante simple, ¿verdad? Incluso en términos de software, no necesita cargar convoluciones (aunque fue difícil para mí encontrar una implementación)

Así es como se ve la clase base de todos los eventos:

Usando UnityEngine; // Sistema.Colecciones.Genéricos; public abstract class CoreEvent: MonoBehaviour ( public CoreEvent nextEvent; // Próximo evento // Public List listaEventos; acción vacía abstracta pública (); )

En los comentarios, proporcioné una lista de eventos que pueden/deberían funcionar. pequeño ejemplo:

Usando UnityEngine; public class LookEvent: CoreEvent ( public override void Action() ( //if(nextEvent != null) nextEvent.Action(); //else print("Look"); ) )

En este ejemplo, solo estoy desencadenando un próximo evento. Para una lista/matriz, use un bucle. Si un evento debe disparar,
no especifiques nada en el campo nextEvent y listo, porque en la implementación, ya nos hemos ocupado del procesamiento en un valor "th" nulo.

Un punto sobre la implementación. Inicialmente, la clase base de eventos no pretendía ser abstracta. Voy a explicar por qué. como viste
en sí mismos, la condición en valor nulo "th está en uno de los eventos. Es decir, dicha condición se hace para cada evento. De hecho, esto no es necesario si no usa procesamiento en paralelo. Inicialmente, la clase no era abstracta y método de acción() era virtual (virtual),
lo que hizo posible verificar la clase base escribiendo una vez y luego haciendo esto:

Public ovveride void Action() ( base.Action(); //Alguna función )

Sin embargo, aquí es más conveniente para alguien. Decidí hacerlo abstracto ya que redujo significativamente la cantidad de código en la clase de evento base + esto,
desde el punto de vista de la programación, tiene más sentido si conoce la definición palabra clave abstracto.

Clase pública HandlerEvents: MonoBehaviour ( lista pública eventos; // Especifique la clase base. public virtual void Launch() ( for (byte countEvent = 0; countEvent< events.Count; countEvent++) { if (events != null) events.Action(); // Вызываем только те события, которые указаны в листе (не null). } } } public enum TriggerType { Enter, Stay, Exit } public class TriggerHandler: HandlerEvents { public TriggerType triggerType; private void OnTriggerEnter2D(Collider2D other) { if (triggerType == TriggerType.Enter && other.GetComponent())Lanzamiento(); ) privado void OnTriggerExit2D(Collider2D otro) ( if (triggerType == TriggerType.Exit && otro.GetComponent ())Lanzamiento(); ) privado void OnTriggerStay2D(Collider2D other) ( if (triggerType == TriggerType.Stay && other.GetComponent ())Lanzamiento(); ) )

Código bastante genérico, ¿verdad? Este es un enfoque muy versátil, ya que puede hacer una llamada de evento que desencadenará otros eventos, y así sucesivamente hasta que se aburra. Hice un activo con una tecnología similar y ha estado allí durante medio año, pero decidí compartirlo aquí, ya que esa versión está desactualizada.

Eso parece ser todo. ¡Si tiene alguna pregunta, pregunte!

Compartiré muchos principios interesantes que utilizo en breve y que pueden ayudar cuando trabajo con Unity.
Bueno, hay organización de proyectos, lectura de XML, organización de código, etc. ¡Pronto!

Los eventos en Unity3D se dividen en tres grandes grupos:

Eventos desencadenados por eventos oil oil (carga de escena, salida de usuario)
Este grupo de eventos se realiza de manera irregular

Eventos generados cuando se dibuja un marco
En este caso, todos los scripts utilizados se llaman en el ciclo de dibujo de pantalla, lo que significa que afectarán directamente a los FPS (fotogramas por segundo). Por lo tanto, aquí debe tener mucho cuidado al trabajar con funciones que requieren mucho tiempo para procesar.

Eventos generados durante el cálculo de la física
Y el último grupo. Para calcular la física, se crea un hilo separado e independiente, en el que los eventos se llaman con un cierto intervalo de tiempo. El tamaño de este intervalo se puede configurar en el elemento de menú: Editar -> Configuración del proyecto -> Tiempo -> Paso de tiempo fijo.

Conociendo este desglose, ya puedes tomar decisiones sobre dónde colocar qué código.
Sin embargo, todos los cálculos realizados tanto en el cálculo físico como en el renderizado afectan la "capacidad de respuesta" del juego. Por lo tanto, al desarrollar una aplicación, es deseable organizar los cálculos más intensivos en recursos en corrutinas.

Ahora vayamos directamente a la traducción de la sección de ayuda.

Orden de ejecución de las funciones de evento
En Unity3D, hay una serie de eventos que se ejecutan en un orden específico. Describimos este orden a continuación:

Despierto: Esta función siempre se llama antes del inicio de cualquier función, así como inmediatamente después de inicializar el prefab.
Activar:(llamado si el objeto está activo): esta función se llama solo después de que el objeto está habilitado.

Antes de la primera actualización del marco

comenzar: se llama antes de que se dibuje el primer cuadro, solo si el script está definido.

entre fotogramas

OnApplicationPause: Este evento se activa al final de un cuadro cuando se detecta una pausa, de hecho, entre actualizaciones normales de cuadros. Después de OnApplicationPause, se dibuja un marco adicional para mostrar la ventana que se muestra durante la pausa.

Orden de actualización
Para realizar un seguimiento de la lógica del juego, la interacción y animación de objetos, la posición de la cámara, etc., hay varios eventos diferentes que puede usar. El mecanismo general para hacer la mayoría de las cosas está en la función Actualizar(), pero también hay otras funciones.

actualización fija: FixedUpdate() no depende de Update(), y se puede llamar con más o menos frecuencia (generalmente se llama con menos frecuencia si el FPS es lo suficientemente alto). Este evento puede activarse varias veces por fotograma si el FPS es bajo, o puede no activarse entre fotogramas si el FPS es alto. Todos los cálculos y actualizaciones de la física del motor se realizan justo después de FixedUpdate(). Al aplicar cálculos de movimiento dentro de FixedUpdate(), no necesita multiplicar su valor por Time.deltaTime. Esto se debe a que FixedUpdate() se llama desde un temporizador independiente de velocidad de fotogramas.
actualizar: Update() se llama una vez por cuadro. Este es el evento principal para dibujar un marco.
actualización tardía: LateUpdate() se llama una vez por cuadro, después de que se haya completado Update(). Cualquier cálculo que se realice en Update() se completará cuando se llame a LateUpdate(). El uso principal de LateUpdate() suele ser el seguimiento de cámaras de terceros. Si realiza el movimiento de su personaje en el evento Update(), entonces los movimientos de la cámara y los cálculos de su ubicación se pueden realizar en el evento LateUpdate(). Esto asegurará que el personaje haya pasado completamente frente a la cámara y haya asegurado su posición.

Representación de escena (Representación)

OnPreCull: Llamado antes de que la escena se monte en la cámara. El ensamblaje determina qué objetos son visibles para la cámara. OnPreCull se llama solo si la escena se "cortará" de objetos invisibles.
OnBecameVisible / OnBecameInvisible: Se llama cuando un objeto se vuelve visible/invisible para cualquier cámara.
OnWillRenderObject: Llamado una vez por cámara si el objeto es visible.
OnPreRender: Llamado antes de que la cámara comience a renderizar la escena.
OnRenderObjeto: Se llama cuando se han dibujado todos los objetos de la escena. Puede usar las funciones GL o Graphics.DrawMeshNow para crear sus dibujos en esta cámara.
OnPostRender: Se llama después de que la escena se representa en la cámara.
OnRenderImage (solo Versión Pro): Se llama después de que se haya renderizado la escena para posprocesar la imagen en la pantalla.
En GUI: llamado varias veces en un marco en respuesta a eventos de interfaz. Los eventos de relleno de posición y color se manejan primero, seguidos por los eventos de entrada de teclado/ratón.
OnDrawGizmos: Se utiliza para dibujar el Gizmo en el escenario.

corrutinas
Normalmente, la llamada a la corrutina se realiza después de que la función Actualizar() haya regresado. Una rutina es una función que puede pausar la ejecución (rendimiento) hasta que se ejecuta. Diferentes usos para las corrutinas:

producir: la corrutina continuará después de todas las funciones Update() que se llamen en el siguiente cuadro.
rendimiento WaitForSeconds(2): Continuar después del tiempo de retraso especificado cuando ya se hayan llamado todas las funciones Update() en el marco
producir WaitForFixedUpdate(): Continúa cuando ya se han llamado todas las funciones FixedUpdate()
rendimiento WWW: Continúa cuando se completa la descarga de contenido WWW.
rendimiento StartCoroutine(MyFunc): Enlaces de coroutine, llamar a un coroutine esperará a que se complete MyFunc.

Destrucción de objetos

Al destruir: Esta función se llama para el último cuadro de la existencia del objeto (el objeto se puede destruir en respuesta a Object.Destroy o cuando se cierra la escena).

al salir
Estas funciones se llaman para todos los objetos activos en la escena:

Al salir de la aplicación: Esta función se llama en todos los objetos del juego antes de que se cierre la aplicación. En el editor, esto sucede cuando el usuario detiene PlayMode. En el reproductor web, esto sucede cuando se cierra el reproductor web.
Al Deshabilitar: Esta función se llama cuando el objeto está deshabilitado o se vuelve inactivo.

Por lo tanto, se produce el siguiente orden de ejecución del script:

Todos los eventos despiertos
Todos los eventos de inicio
bucle (con paso en tiempo delta variable)
-todas las características de FixedUpdate
-desarrollo del motor de física
- activar eventos OnEnter/Exit/Stay
- Eventos de colisión OnEnter/Exit/Stay
Rigidbody se transforma según transform.position y rotación
OnMouseDown/OnMouseUp otros eventos de entrada
Todos los eventos Update()
Animación, fusión y transformación.
Todos los eventos de LateUpdate
Representación

Consejos
Si ejecuta rutinas en LateUpdate, también se llamarán después de LateUpdate justo antes de renderizar.
Las corrutinas se ejecutan después de todas las funciones Update().

Al trabajar con el motor de juego Unity3D, uno de los primeros conceptos que debe aprender es el orden en que se llaman los eventos en el juego y el procesamiento de estos mismos eventos.

Aunque hay bastante información en ruso sobre este motor, no encontré una descripción correcta de los eventos. Pero encontré el artículo en inglés Execution Order of Event Functions de la ayuda de Unity3D.

Prefacio del traductor

Pero, antes de comenzar con la referencia oficial, quiero señalar que los eventos en Unity3D se dividen en cuatro grandes grupos:

  1. Eventos generados cuando se dibuja un marco
    En este caso, todos los scripts utilizados se llaman en el ciclo de dibujo de pantalla, lo que significa que afectarán directamente a los FPS (fotogramas por segundo). Por lo tanto, aquí debe tener mucho cuidado al trabajar con funciones que requieren mucho tiempo para procesar.
  2. Eventos generados durante el cálculo de la física
    Para calcular la física, se crea un hilo separado e independiente, en el que los eventos se llaman con un cierto intervalo de tiempo. El tamaño de este intervalo se puede configurar en el elemento de menú: Editar -> Configuración del proyecto -> Tiempo -> Paso de tiempo fijo.
  3. Corrutinas (Corrutinas).
    Y el último grupo. Si es muy remota, entonces se pueden comparar con procesos separados, pero dado que Unity3D no permite la creación de subprocesos separados, entonces esto es una especie de compromiso. Le permite interrumpir los cálculos, dar recursos al hilo principal y luego reanudar la siguiente parte de los cálculos. Un ejemplo sorprendente- recálculo constante del costo de los bienes en diferentes puntos de venta. Irá solo, no ralentizará el proceso del juego y los precios en las tiendas siempre estarán actualizados.

Conociendo este desglose, ya puedes tomar decisiones sobre dónde colocar qué código.

Sin embargo, todos los cálculos realizados tanto en el cálculo físico como en el renderizado afectan la "capacidad de respuesta" del juego. Por lo tanto, al desarrollar una aplicación, no olvide dividir los cálculos que requieren más recursos en etapas y organizarlos en rutinas.

Ahora vayamos directamente a la traducción de la sección de ayuda.

Orden de ejecución de las funciones de evento

En Unity3D, hay una serie de eventos que se ejecutan en un orden determinado. Describimos este orden a continuación:

Carga de la primera escena

Estas funciones se llaman cuando comienza la escena (una vez para cada objeto en el cuadro).

  • Despierto: Esta función siempre se llama antes del inicio de cualquier función, así como inmediatamente después de inicializar el prefab.
  • Activar:(llamado si el objeto está activo): esta función se llama solo después de que el objeto está habilitado.

Antes de la primera actualización del marco

  • comenzar: se llama antes de que se dibuje el primer cuadro, solo si el script está definido.

entre fotogramas

  • OnApplicationPause: Este evento se activa al final de un cuadro cuando se detecta una pausa, de hecho, entre actualizaciones normales de cuadros. Después de OnApplicationPause, se dibuja un marco adicional para mostrar la ventana que se muestra durante la pausa.

Orden de actualización

Para realizar un seguimiento de la lógica del juego, la interacción y animación de objetos, la posición de la cámara, etc., hay varios eventos diferentes que puede usar. El mecanismo general para hacer la mayoría de las cosas está en la función Actualizar(), pero también hay otras funciones.

  • actualización fija: FixedUpdate() no depende de Update(), y se puede llamar con más o menos frecuencia (generalmente se llama con menos frecuencia si el FPS es lo suficientemente alto). Este evento puede activarse varias veces por fotograma si el FPS es bajo, o puede no activarse entre fotogramas si el FPS es alto. Todos los cálculos y actualizaciones de la física del motor se realizan justo después de FixedUpdate(). Al aplicar cálculos de movimiento dentro de FixedUpdate(), no necesita multiplicar su valor por Time.deltaTime. Esto se debe a que FixedUpdate() se llama desde un temporizador independiente de velocidad de fotogramas.
  • actualizar: Update() se llama una vez por cuadro. Este es el evento principal para dibujar un marco.
  • actualización tardía: LateUpdate() se llama una vez por cuadro, después de que se haya completado Update(). Cualquier cálculo que se realice en Update() se completará cuando se llame a LateUpdate(). El uso principal de LateUpdate() suele ser el seguimiento de cámaras de terceros. Si realiza el movimiento de su personaje en el evento Update(), entonces los movimientos de la cámara y los cálculos de su ubicación se pueden realizar en el evento LateUpdate(). Esto asegurará que el personaje haya pasado completamente frente a la cámara y haya asegurado su posición.

Representación de escena (Representación)

  • OnPreCull: Llamado antes de que la escena se monte en la cámara. El ensamblaje determina qué objetos son visibles para la cámara. OnPreCull se llama solo si la escena se "cortará" de objetos invisibles.
  • OnBecameVisible / OnBecameInvisible: Se llama cuando un objeto se vuelve visible/invisible para cualquier cámara.
  • OnWillRenderObject: Llamado una vez por cámara si el objeto es visible.
  • OnPreRender: Llamado antes de que la cámara comience a renderizar la escena.
  • OnRenderObjeto: Se llama cuando se han dibujado todos los objetos de la escena. Puede usar las funciones GL o Graphics.DrawMeshNow para crear sus dibujos en esta cámara.
  • OnPostRender: Se llama después de que la escena se representa en la cámara.
  • OnRenderImage(Solo en la versión Pro): se llama después de que se haya renderizado la escena, para posprocesar la imagen en la pantalla.
  • En GUI: llamado varias veces en un marco en respuesta a eventos de interfaz. Los eventos de relleno de posición y color se manejan primero, seguidos por los eventos de entrada de teclado/ratón.
  • OnDrawGizmos: Se utiliza para dibujar el Gizmo en el escenario.

corrutinas

Normalmente, la llamada a la corrutina se realiza después de que la función Actualizar() haya regresado. Una rutina es una función que puede pausar la ejecución (rendimiento) hasta que se ejecuta. Diferentes usos para las corrutinas:

  • producir: la corrutina continuará después de todas las funciones Update() que se llamen en el siguiente cuadro.
  • rendimiento WaitForSeconds(2): Continuar después del tiempo de retraso especificado cuando ya se hayan llamado todas las funciones Update() en el marco
  • producir WaitForFixedUpdate(): Continúa cuando ya se han llamado todas las funciones FixedUpdate()
  • rendimiento StartCoroutine(MyFunc): Enlaces de coroutine, llamar a un coroutine esperará a que se complete MyFunc.

Destrucción de objetos

  • Al destruir: Esta función se llama para el último cuadro de la existencia del objeto (el objeto se puede destruir en respuesta a Object.Destroy o cuando se cierra la escena).

al salir

Estas funciones se llaman para todos los objetos activos en la escena:

  • Al salir de la aplicación: Esta función se llama en todos los objetos del juego antes de que se cierre la aplicación. En el editor, esto sucede cuando el usuario detiene PlayMode. En el reproductor web, esto sucede cuando se cierra el reproductor web.
  • Al Deshabilitar: Esta función se llama cuando el objeto está deshabilitado o se vuelve inactivo.

Así, al finalizar, los eventos se disparan en el siguiente orden:

  • Todos los eventos despiertos
  • Todos los eventos de inicio
  • bucle (con paso en tiempo delta variable)
    • Todas las funciones de actualización fijas
    • desarrollo del motor de física
    • desencadenar eventos OnEnter/Exit/Stay
    • eventos de colisión OnEnter/Exit/Stay
  • Rigidbody se transforma según transform.position y rotación
  • OnMouseDown/OnMouseUp otros eventos de entrada
  • Todos los eventos Update()
  • Animación, fusión y transformación.
  • Todos los eventos de LateUpdate
  • Representación

Si ejecuta rutinas en LateUpdate, también se llamarán después de LateUpdate justo antes de renderizar.

Las corrutinas se ejecutan después de todas las funciones Update().

PD adición del usuario Leopotam

Corrutina es solo un fragmento de código que se ejecuta en el hilo principal. Esto es muy importante de entender, porque simplemente poner un cálculo pesado en una corrutina y asumir que todo estará bien es fundamentalmente incorrecto, los cálculos simplemente obstruirán el flujo de la misma manera que si se realizaran en Actualizar o en algún otro lugar en métodos estándar. Es necesario dividir los cálculos en iteraciones para que el proceso continúe durante iteraciones repetidas. El objetivo de las corrutinas es automatizar la llamada a estas iteraciones en cada ciclo de dibujo.

Por ejemplo:

IEnumerator FindBozons() ( var isFound = false ; var colliderSectionID = 0 ; var colliderSectionCount = 10 ; while (! isFound) ( // Procesando solo una sección a la vez para reducir la carga isFound = ProcessDataFromSection(colliderSectionID) ; colliderSectionID = (colliderSectionID++) % colliderSectionCount; rendimiento retorno nulo; ) // Compramos yates / barcos de vapor // Salidas de rutina) void Inicio() ( StartCoroutine(FindBozons() ) ; )

El mecanismo de rutina guardará automáticamente el estado del contexto de ejecución de la función y volverá al punto de interrupción (rendimiento).

La creación de scripts en Unity no es como la idea tradicional de un programa, donde el código se ejecuta constantemente en un bucle hasta que completa su tarea. En cambio, Unity transfiere periódicamente el control al script cuando se llaman ciertas funciones declaradas en él. Tan pronto como la función termina de ejecutarse, el control vuelve a Unity. Estas funciones se conocen como funciones de evento porque son activados por Unity en respuesta a eventos que ocurren durante el juego. Unity usa un esquema de nombres para determinar qué función llamar para un evento en particular. Por ejemplo, ya ha visto la función Actualizar (llamada antes de un cambio de cuadro) y la función Iniciar (llamada justo antes del primer cuadro del objeto). Mucho está disponible en Unity gran cantidad funciones de eventos; Lista llena Con información adicional su uso se puede encontrar en la página de documentación de la clase MonoBehaviour. Los siguientes son algunos de los eventos más importantes y frecuentes.

Eventos regulares de actualización

Un juego es algo así como una animación en la que los cuadros se generan sobre la marcha. Un concepto clave en la programación de juegos es cambiar la posición, el estado y el comportamiento de los objetos en el juego justo antes de que se dibuje un marco. Dicho código en Unity generalmente se coloca en la función Actualizar. La actualización se llama antes de que se dibuje el marco y antes de que se calculen las animaciones.

Void Update () ( distancia flotante = velocidad * Tiempo.deltaTiempo * Entrada.GetAxis("Horizontal"); transform.Translate(Vector3.right * distancia); )

El motor de física también se actualiza en pasos de tiempo fijo, similar a cómo funciona la representación de cuadros. Se llama a una función de evento FixedUpdate separada justo antes de cada actualización de los datos físicos. Porque la física y el marco no se actualizan con la misma frecuencia, obtendrá resultados más precisos del código de física si lo coloca en la función FixedUpdate en lugar de Actualizar.

Void FixedUpdate() ( Vector3 force = transform.forward * driveForce * Input.GetAxis("Vertical"); rigidbody.AddForce(force); )

A veces, también es útil poder realizar cambios adicionales en el momento en que todos los objetos de la escena hayan completado las funciones de actualización y actualización fija y se hayan calculado todas las animaciones. Como ejemplo, la cámara debe permanecer bloqueada en el objetivo; el ajuste de la orientación de la cámara se debe realizar después de que el objeto de destino se haya movido. Otro ejemplo es cuando el código del script necesita anular un efecto de animación (digamos que la cabeza del personaje gire hacia el objeto de destino en la escena). En este tipo de situaciones, puede utilizar la función LateUpdate.

Void LateUpdate() ( Camera.main.transform.LookAt(target.transform); )

Eventos de inicialización

Suele ser útil poder llamar al código de inicialización antes de que se produzcan actualizaciones durante el juego. La función de inicio se llama antes de que se actualice el primer marco o la física del objeto. La función Awake se llama para cada objeto en la escena cuando se carga la escena. Tenga en cuenta que, aunque para diferentes objetos, las funciones Start y Awake se llaman en un orden diferente, todos los Awake se ejecutarán antes de que se llame el primer Start. Esto significa que el código de la función Inicio puede usar lo que se haya hecho en la fase Despertar.

Eventos de GUI

Unity tiene un sistema para dibujar controles GUI encima de todo en la escena y responder a los clics en esos controles. Este código se maneja de manera un poco diferente a una actualización de marco normal, por lo que debe colocarse en una función OnGUI que se llamará periódicamente.

Void OnGUI() ( GUI.Label(labelRect, "Game Over"); )

También puede definir eventos de mouse que se activan en un GameObject en la escena. Esto se puede usar para apuntar armas o para mostrar información del personaje debajo del cursor del mouse. Hay un conjunto de funciones de eventos OnMouseXXX (por ejemplo, OnMouseOver, OnMouseDown) que permiten que el script responda a las acciones del mouse del usuario. Por ejemplo, si se presiona el botón del mouse mientras el cursor del mouse está sobre un objeto determinado, si la función OnMouseDown está presente en el script del objeto, se llamará.

Eventos de física

El motor de física informará las colisiones con un objeto llamando a las funciones de eventos en el script de ese objeto. Funciones


¡Buen día!

Hoy me gustaría hablar brevemente sobre el uso de eventos para deshacerse de la basura y proporcionar una funcionalidad compleja y dinámica al código. Cabe señalar que este artículo está dirigido más a principiantes que desean aprender más sobre los sistemas de eventos.

Analizaremos todo esto usando el ejemplo de un sistema de control de sonido. Este sistema nos permitirá activar/desactivar la música y los sonidos en los ajustes del juego.

Antes de crear una clase de administrador que administrará la configuración de sonido y música, crearemos una clase serializable simple. Se utilizará como modelo de datos para guardar en JSON.

Usando System.Collections; usando System.Collections.Generic; utilizando UnityEngine; //========================================== // Modelo de configuración de audio // @modelo de uso para la configuración de audio // // Desarrollado por CodeBits Interactive // ​​​​https://cdbits.net/ //====================== ====================== public class AudioSettingsModel ( public bool music = true; // Flag responsable de la música public bool sounds = true; // Flag, responsable de suena
Ahora podemos comenzar a escribir la clase de administrador. Lo instalaremos en la primera etapa. Este administrador será un objeto global y no se eliminará al pasar de una escena a otra.

Usando System.Collections; usando System.Collections.Generic; utilizando UnityEngine; utilizando System.IO; //========================================== // Administrador de audio / / @usage funciona con la configuración de audio // // Desarrollado por CodeBits Interactive // ​​https://cdbits.net/ //===================== ======================= public class AudioManager: MonoBehaviour( // Configuración pública public static AudioManager instance = null; // Manager instancia public static AudioSettingsModel settings = null ; // Modelo de configuración de audio cadena estática privada _settings_path = ""; // Ruta al archivo de configuración de audio // Inicializa el administrador void Awake()( // Establece la ruta para guardar la configuración _settings_path = Application.persistentDataPath + "/audioSettings .gdf" ; // Comprueba si nuestra instancia de administrador está configurada if (instancia == null)( // La instancia no está configurada instancia = esto; // Establece el objeto actual en la instancia) // Establece un parámetro que indique // eso objeto dado no debe eliminarse cuando el nivel // está descargado DontDestroyOnLoad(gameObject); // Inicializar la configuración de nuestro administrador InitializeSettings(); ) // Inicializar el administrador privado void InitializeSettings()( // Si el modelo de configuración no está configurado if (settings == null) settings = new AudioSettingsModel(); // Crear nuevo modelo if (File.Exists(_settings_path))( // Si existe un archivo con la configuración loadSettings(); // Cargar el archivo de configuración de audio ) ) // Cargar la configuración de audio public void loadSettings()( string _data = File.ReadAllText(_settings_path); // Leer todo el texto de la configuración del archivo = JsonUtility.FromJson (_datos); // Deserializarlo al modelo actual) // Guardar la configuración de audio public void saveSettings()( string _json_data = JsonUtility.ToJson(settings); // Serializar la configuración actual del modelo File.WriteAllText(_settings_path, _json_data); / / Guardar en nuestro archivo ) // Crear delegados para nuestro evento, que luego // se utilizarán para realizar un seguimiento de los cambios en la configuración de audio público delegado void AudioSettingsChanged(); // Agregar un nuevo evento público de delegado AudioSettingsChanged OnAudioSettingsChanged; // Crear un evento basado en él // Habilitar/deshabilitar sonidos public void toggleSounds(bool habilitado)( settings.sounds = habilitado; // Cambiar la configuración de sonido en el modelo actual saveSettings(_settings_path, settings); // Guardar la configuración si ( OnAudioSettingsChanged ! = null) OnAudioSettingsChanged(); // Llamar a nuestro evento ) // Habilitar/deshabilitar música public void toggleMusic(bool habilitado)( settings.music = habilitado; // Cambiar la configuración de música en el modelo actual saveSettings(_settings_path, settings) ; // Guarda la configuración si (OnAudioSettingsChanged != null) OnAudioSettingsChanged(); // Llama a nuestro evento ) )
Ahora que el administrador está listo, puede crear un objeto vacío en su escena inicial y nombrarlo, por ejemplo "_AUDIO_MANAGER", luego agréguele nuestra clase de administrador. Esto se puede hacer simplemente llamando al menú para agregar un componente en el objeto y seleccionando "Administradores de juegos" => "Administrador de audio".

Después de eso, necesitamos escribir un componente que acoplaremos a cada objeto con AudioSource.

Usando System.Collections; usando System.Collections.Generic; utilizando UnityEngine; //========================================== // Silenciador de audio / / @uso on/off fuentes de audio en objetos // // Desarrollado por CodeBits Interactive // ​​​​https://cdbits.net/ //================== =========================== public class AudioMuter: MonoBehaviour ( // Parámetros públicos del componente public bool is_music = false; // Esta bandera aclara a nuestra clase si la fuente de audio es sonido o música. // Parámetros privados private AudioSource _as; // Fuente de audio private float _base_volume = 1F; // Volumen base de la fuente de audio // Inicializa el objeto void Start()( // Obtener el componente AudioSource y su volumen inicial _as = this.gameObject.GetComponent (); // Obtener componente _base_volume = _as.volume; // Obtenga el volumen base // Aquí agregamos un oyente que ejecutará el método _audioSettingsChanged // cuando la configuración de música/sonidos haya cambiado AudioManager.instance.OnAudioSettingsChanged += _audioSettingsChanged; // Establecer // Bueno, al principio, debemos comprobar Estado actual sonidos/música _audioSettingsChanged(); ) // Cuando se destruye el objeto void OnDestroy()( AudioManager.instance.OnAudioSettingsChanged -= _audioSettingsChanged; // Destruye el oyente ) // Este método se usa para habilitar/deshabilitar el volumen de AudioSource privado void _audioSettingsChanged()( if (is_music) _as.volume = (AudioManager.settings.music) ? _base_volume: 0F; if (!is_music) _as.volume = (AudioManager.settings .sonidos) ?_volumen_base: 0F; ) )
De esta manera podemos controlar los sonidos/música en el juego. Este ejemplo de ninguna manera le dice cómo hacerlo correctamente, sino que solo demuestra el funcionamiento del sistema de eventos y los oyentes en Unity3D.

Y finalmente, quiero hablar sobre lo que acabamos de usar. En el siguiente ejemplo, se declaró un delegado a partir del cual se creó el oyente:

Delegado público void AudioSettingsChanged(); evento público AudioSettingsChanged OnAudioSettingsChanged;
Puede configurar el oyente para que se ejecute bajo ciertas condiciones y vincular ciertos métodos a ellos, que se ejecutarán cuando se cumplan estas condiciones.

Y con la ayuda de los delegados, sobre la base de los cuales creamos el oyente, puede crear funciones de devolución de llamada. Esto puede ser especialmente útil para métodos asincrónicos (por ejemplo, al enviar solicitudes POST asincrónicas).

Espero que mi poca experiencia en esta materia os sea de utilidad y podáis aplicar este ejemplo a vuestros proyectos. También estaré encantado de responder a sus preguntas (si algo no está claro para alguien).

Puedes ayudar y transferir algunos fondos para el desarrollo del sitio.