For the complete documentation index, see llms.txt. This page is also available as Markdown.

Systems

Aprende cómo se usan los Systems para actualizar el estado de la escena

Las escenas de Decentraland dependen de systems para actualizar cualquier dato con el tiempo, incluida la información almacenada en el components.



systems son lo que hace que las escenas sean dinámicas; son funciones que se ejecutan periódicamente en cada tick del game loop de la escena y cambian lo que se renderizará.

El siguiente ejemplo muestra una declaración básica de un sistema:

La función de un sistema puede hacer lo que quieras. Normalmente, actuará sobre todas las entidades que cumplan ciertos criterios de consulta, siguiendo cierta lógica para cambiar los valores almacenados en los componentes de la entidad.

En el ejemplo anterior, el sistema MoveSystem es una función que se ejecuta en cada tick del game loop, cambiando la posición de cada entidad en la escena que tenga un Transform.



Puedes tener múltiples sistemas en tu escena para desacoplar distintos comportamientos, haciendo que tu código sea más limpio y más fácil de escalar y reutilizar. Por ejemplo, un sistema podría encargarse de la física, otro podría hacer que una entidad obstáculo se mueva continuamente de un lado a otro, otro podría manejar la IA de los personajes.

Múltiples sistemas pueden actuar sobre una sola entidad. Por ejemplo, un personaje no jugador podría moverse por su cuenta según una IA, pero también verse afectado por la gravedad cuando camina accidentalmente por un precipicio. En ese escenario, los sistemas de física y de IA ni siquiera necesitan saber el uno del otro. Cada uno vuelve a evaluar de forma independiente su estado actual en cada tick del game loop e implementa su propia lógica por separado.

La función del sistema

La función de un sistema se ejecuta periódicamente, una vez en cada tick del game loop. Esto ocurre automáticamente; no necesitas llamar explícitamente a esta función desde ningún lugar de tu código.

En una escena de Decentraland, puedes pensar en el game loop como la agregación de todas las funciones de sistema de tu escena.

Manejar entidades por referencia

Algunos componentes y sistemas están pensados para usarse solo en una entidad de la escena. Por ejemplo, en una entidad que almacena el puntaje de un juego o quizá una puerta principal que es única en la escena. Para acceder a una de esas entidades dentro de un sistema, simplemente puedes referirte a la entidad o a sus componentes por nombre en las funciones del sistema.

Para proyectos más grandes, recomendamos que mantengas las definiciones de los sistemas en archivos separados de la instanciación de entidades y componentes.

Iterar sobre una consulta de componentes

Muchas veces, tu escena tendrá múltiples entidades del mismo tipo que tendrán comportamientos similares. Por ejemplo, muchas puertas que se pueden abrir, o muchos enemigos que pueden atacar al jugador. Tiene sentido manejar todas estas entidades similares en un solo sistema, iterando sobre la lista y realizando las mismas comprobaciones en cada una.

No quieres que la función de un sistema itere sobre todo el conjunto de entidades en la escena, ya que esto podría ser muy costoso en términos de capacidad de procesamiento. Para evitar esto, puedes consultar components, para iterar solo sobre las entidades relevantes.

Por ejemplo, tu escena puede tener un PhysicsSystem sistema que calcula el efecto de la gravedad sobre las entidades de tu escena. Algunas entidades de tu escena, como los árboles, no están pensadas para moverse nunca; así que sería inteligente evitar calcular los efectos de la gravedad sobre ellas. Puedes definir un componente HasPhysics para marcar las entidades que podrían verse afectadas por la gravedad, y luego hacer que PhysicsSystem solo se ocupe de las entidades devueltas por esta consulta.

Tiempo delta entre frames

La función de un sistema puede incluir opcionalmente un argumento llamado dt, de tipo number (que representa delta time).

delta time representa el tiempo transcurrido desde el último tick del game loop, en segundos.

El dt el argumento es el tiempo real que ha transcurrido desde el último tick del game loop, medido en segundos. El SDK no impone una frecuencia de ticks fija: el runtime host pasa este valor y varía según la frecuencia de fotogramas de la escena.

Cuanto más fluida se ejecute una escena, con más frecuencia ocurren los ticks y menor es cada dt valor. Cuando un tick tarda más en procesarse, pasa más tiempo antes del siguiente y dt crece en consecuencia.

Esta frecuencia de fotogramas del lado de la escena está limitada a 30 ticks por segundo, en cuyo caso el valor de dt es 1/30 (0.0333...).



Cuando el procesamiento de un frame tarda más, el renderizado de ese frame se retrasa, y el dt pasado al siguiente tick refleja ese intervalo más largo. El engine no compensa el retraso de forma retroactiva; dt siempre informa el tiempo real transcurrido para que tus sistemas puedan ajustarse a ello.



Idealmente, deberías evitar que tu escena pierda frames, ya que afecta la calidad de la experiencia del jugador. Dado que esto depende de la capacidad de procesamiento de la máquina del jugador, siempre existe la posibilidad de que tu escena deba estar preparada para manejarlo con gracia.

El dt La variable es útil cuando el procesamiento del frame supera el tiempo predeterminado. Suponiendo que el frame actual tardará tanto como el anterior, esta información puede usarse para calcular cuánto ajustar un cambio gradual, de modo que la tasa de cambio parezca constante y en proporción al retraso entre frames.

Consulta posicionamiento de entidades para ver ejemplos de cómo usar dt para hacer el movimiento más suave.

Iterar en un intervalo de tiempo

Si quieres que un sistema ejecute algo a intervalos regulares de tiempo, puedes hacerlo combinando el dt argumento con un temporizador.

También hay una función de atajo setInterval y clearInterval que usa Systems en segundo plano. Esto permite una versión más fácil y corta cuando la intención es ejecutar una cierta función cada X cantidad de tiempo.

Donde el primer argumento, callback, es la función que se ejecutará (en este caso, la console.log()), y el segundo argumento, ms(10000 en este caso), es la cantidad de milisegundos a esperar entre cada ejecución de la función.

Para detener el setInterval función, clearInterval se usa.

Donde intervalId es la referencia al setInterval return definido anteriormente.

Para casos de uso más complejos, donde puedan crearse dinámicamente múltiples retrasos e iteraciones, podría valer la pena definir un componente personalizado para almacenar un valor de temporizador individual para cada entidad. Consulta Componentes personalizados.

Orden de ejecución de los sistemas

En algunos casos, cuando tienes múltiples sistemas en ejecución, te puede importar qué sistema se ejecuta primero en tu escena.

Por ejemplo, podrías tener un de física sistema que actualiza la posición de las entidades en la escena, y otro de límites sistema que garantiza que ninguna de las entidades se posicione fuera de los límites de la escena. En este caso, quieres asegurarte de que el de límites sistema se ejecute al final. De lo contrario, el de física sistema podría mover las entidades fuera de los límites de la escena, pero el de límites sistema no se enterará hasta que se ejecute de nuevo en el siguiente frame.

Al agregar un system al engine, establece un priority campo opcional para determinar cuándo se ejecuta el sistema en relación con otros sistemas.

Los sistemas con un número de prioridad mayor se ejecutan primero, así que un sistema con una prioridad de 5 se ejecuta antes que uno con prioridad 1.

A los sistemas a los que no se les asigna una prioridad explícita se les asigna una prioridad predeterminada de 100000. Como los números más altos se ejecutan primero, estos sistemas se ejecutan antes que los que tienen una prioridad explícita más baja.

Si dos sistemas tienen el mismo número de prioridad, no hay forma de saber con certeza cuál de ellos se ejecutará primero.

Eliminar un sistema

Se puede agregar o eliminar una instancia de un sistema del engine para activarlo o desactivarlo.

Si un sistema está definido pero no se agrega al engine, su función no es llamada por el engine.

Para eliminar un sistema, primero debes darle un nombre al agregarlo al engine, para poder referirte al sistema más adelante.

La cadena que pasas a engine.removeSystem() debe coincidir con el nombre que asignaste al sistema cuando lo agregaste.

Otra forma de eliminar un sistema es pasar la propia función del sistema a engine.removeSystem() el método. De esta forma no necesitas darle un nombre al sistema cuando lo agregas.

engine.removeSystem() acepta ya sea la cadena de nombre que asignaste al agregar el system, o una referencia a la propia función del system.

Puedes usar el método de abajo para hacer que un sistema se elimine automáticamente cuando su propósito se complete.

Última actualización