# Systems

Decentraland scenes dependen de *systems* para actualizar cualquier dato a lo largo del tiempo, incluida la información almacenada en cada entity's [components](/creator/content-creator-es/scenes-sdk7/arquitectura/entities-components.md).

![](/files/f8ae24ca96098f4c403470a24f18af76952e3f4c)

*systems* son lo que hace que las scenes sean dinámicas; son funciones que se ejecutan periódicamente en cada tick del game loop de la scene, cambiando lo que se va a renderizar.

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

```ts
// Define the system
function mySystem() {
  console.log("Performed on every tick. My system is running")
}
// Add system to engine
engine.addSystem(mySystem)
```

La función en un system puede hacer cualquier cosa que quieras. Normalmente, actuará sobre todas las entities que cumplan ciertas [query](/creator/content-creator-es/scenes-sdk7/arquitectura/querying-components.md), siguiendo cierta lógica para cambiar los valores almacenados en los components de la entity.

```ts
function moveSystem(dt: number) {
  // iterate over all entiities with a Transform
  for (const [entity] of engine.getEntitiesWith(Transform)) {

  // fetch a mutable Transform component
  const transform = Transform.getMutable(entity)

  // update the position value
    transform.position.z += 0.01
  }
}

engine.addSystem(moveSystem)
```

En el ejemplo anterior, el system `MoveSystem` es una función que se ejecuta en cada tick del game loop, cambiando la posición de cada entity de la scene que tiene un Transform.

![](/files/83b06b1db5e34978d664e015635a62c013905046)

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

Varios systems pueden actuar sobre una sola entity. Por ejemplo, un personaje no jugador podría moverse por su cuenta en función de una IA, pero también verse afectado por la gravedad cuando camina accidentalmente por el borde de un precipicio. En ese escenario, los systems de física y de IA ni siquiera necesitan conocerse entre sí. Reevalúan de forma independiente su estado actual en cada tick del game loop e implementan su propia lógica por separado.

## La función del system

La función de un system se ejecuta periódicamente, una vez por 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 scene de Decentraland, puedes pensar en el game loop como la agregación de todas las funciones de system en tu scene.

{% hint style="warning" %}
**📔 Nota**: Si agregas múltiples instancias de un mismo system al engine, la función se ejecutará varias veces por tick del game loop. Por ejemplo, agregar un system dos veces podría hacer que una entity se mueva al doble de la velocidad esperada, ya que avanza dos incrementos en cada tick.
{% endhint %}

## Manejar entities por referencia

Algunos components y systems están pensados para usarse solo en una entity de la scene. Por ejemplo, en una entity que almacena la puntuación de un juego o quizá una puerta principal que es única en la scene. Para acceder a una de esas entities dentro de un system, simplemente puedes referirte a la entity o a sus components por nombre en las funciones del system.

```ts
export function main(){
	// create a new entity
	const game = engine.addEntity()

	// add component to that entity
	ScoreComponent.create(game)
}

// Define the system
export function UpdateScore() {

  // call reference to individual entity
  const points = ScoreComponent.get(game).points
  console.log(points)
}

// Add system to engine
engine.addSystem(UpdateScore)
```

Para proyectos más grandes, recomendamos que mantengas las definiciones de system en archivos separados de la instanciación de entities y components.

## Recorrer una query de component

Muchas veces, tu scene tendrá múltiples entities 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 entities similares en un solo system, iterando sobre la lista y realizando las mismas comprobaciones en cada una.

No querrás que la función de un system recorra *todo el* conjunto de entities de la scene, ya que esto podría ser muy costoso en términos de potencia de procesamiento. Para evitar esto, puedes [consultar components](/creator/content-creator-es/scenes-sdk7/arquitectura/querying-components.md), para iterar solo sobre las entities relevantes.

Por ejemplo, tu scene puede tener un `PhysicsSystem` que calcule el efecto de la gravedad sobre las entities de tu scene. Algunas entities de tu scene, 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 component `HasPhysics` para marcar las entities que podrían verse afectadas por la gravedad, y luego tener `PhysicsSystem` solo ocuparse de las entities devueltas por esta query.

```ts
// Define the system
export function PhysicsSystem() {
  // iterate over all entiities with a HasPhysics
  for (const [entity] of engine.getEntitiesWith(HasPhysics)) {

  // fetch a mutable Transform component
  const transform = Transform.getMutable(entity)

  // Calculate effect of physics
  }
}

// Add system to engine
engine.addSystem(PhysicsSystem)
```

## Delta time between frames

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

```ts
function MySystem(dt: number) {

  // Udate scene
  console.log("time since last tick: ", dt)
}

engine.addSystem(MySystem)
```

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

Las scenes de Decentraland se actualizan de forma predeterminada a 30 ticks por segundo. Esto significa que el `dt` argumento pasado a todos los systems tenderá a ser igual a *1/30* (0.0333...).

Si el procesamiento de un frame tarda menos que este intervalo, entonces el engine esperará el tiempo restante para mantener las actualizaciones con un ritmo regular y `dt` permanecerá igual a *1/30* .

![](/files/4fe56eb9625a84e51e85f23ed1e14de4a01500e9)

Si el procesamiento de un frame tarda más de *1/30* segundos, el dibujo de ese frame se retrasa. Entonces el engine intenta terminar ese frame y mostrarlo lo antes posible. Luego pasa al siguiente frame e intenta mostrarlo *1/30* segundos después del frame anterior. No compensa el retraso previo.

![](/files/8f0cfedaf4c0d5bd4feb7ac252b368c6448116a3)

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

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

Consulta [entity positioning](/creator/content-creator-es/scenes-sdk7/esenciales-de-contenido-3d/entity-positioning.md) para ver ejemplos de cómo usar `dt` para hacer que el movimiento sea más fluido.

## Loop at a timed interval

Si quieres que un system ejecute algo en un intervalo de tiempo regular, puedes hacerlo combinando el `dt` argumento con un temporizador.

```ts
let timer: number = 10

function LoopSystem(dt: number) {
  timer -= dt
  if (timer <= 0) {
      timer = 10
      // DO SOMETHING
    }
}

engine.addSystem(LoopSystem)
```

También existe una función de acceso rápido `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 cierta función cada X cantidad de tiempo.

```ts
const intervalId = timers.setInterval(() => {
    console.log('Printing this every 10 seconds')
}, 10000)
```

Donde el primer argumento, `callback`, es la función que se va a ejecutar (en este caso, el `console.log()`), y el segundo argumento, `ms`(1000 en este caso), son los milisegundos que se esperan entre cada ejecución de la función.

Para detener el `setInterval` , `clearInterval` se usa.

```
timers.clearInterval(intervalId)
```

Donde `intervalId` es la referencia al `setInterval` return definida antes.

Para casos de uso más complejos, en los que puede haber múltiples retrasos y loops creándose dinámicamente, puede valer la pena definir un component personalizado para almacenar un valor de temporizador individual para cada entity. Ver [Custom components](/creator/content-creator-es/scenes-sdk7/arquitectura/custom-components.md).

## System execution order

En algunos casos, cuando tienes varios systems ejecutándose, puede importarte qué system ejecuta tu scene primero.

Por ejemplo, podrías tener un system de *physics* que actualice la posición de las entities en la scene, y otro system de *boundaries* que garantice que ninguna de las entities esté posicionada fuera de los límites de la scene. En este caso, quieres asegurarte de que el system de *boundaries* se ejecute al final. De lo contrario, el system de *physics* podría mover entities fuera de los límites de la scene, pero el system de *boundaries* no se enterará hasta que se ejecute de nuevo en el siguiente frame.

Al agregar un system al engine, define opcionalmente un campo `priority` para determinar cuándo se ejecuta el system en relación con otros systems.

```ts
engine.addSystem(PhysicsSystem, 1)
engine.addSystem(BoundariesSystem, 5)
```

Los systems con un número de priority más bajo se ejecutan primero, así que un system con una priority de *1* se ejecuta antes que uno con priority *5*.

Los systems a los que no se les asigna una priority explícita tienen una priority predeterminada de *0*, así que estos se ejecutan primero.

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

## Eliminar un system

Una instancia de un system puede agregarse o eliminarse del engine para activarlo o desactivarlo.

Si un system está definido pero no se agrega al engine, el engine no llama a su función.

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

```ts
// declare system
function mySystem(dt: number){
  console.log("delay since last tick: ", dt)
}

// add system (giving it a priority and name)
engine.addSystem(mySystem, 1, "DelaySystem")

// remove system
engine.removeSystem("DelaySystem")
```

Una scene puede tener potencialmente varias instancias de un mismo system ejecutándose juntas, así que necesitas decirle al engine cuál de ellas eliminar.

Otra forma de eliminar un system es declarar un pointer al system y luego pasar ese pointer al `engine.removeSystem()` método.

```ts
// declare system
function mySystem(dt: number){
  console.log("delay since last tick: ", dt)
}

// add system (making a pointer)
const mySystemInstance = engine.addSystem(mySystem)

// remove system
engine.removeSystem(mySystemInstance)
```

Ten en cuenta que el pointer es a la *instance* del system, no a la class del system. En el ejemplo anterior, `engine.removeSystem()` no se está pasando `mySystem` (la declaración de la class del system). Se está pasando `mySystemInstance` (la instance que se agregó al engine).

Puedes usar el método de abajo para hacer que un system se termine a sí mismo cuando su propósito esté completo.

```ts
   const mySystem = function(dt: number){
        time += dt
        if(time > 3){
		engine.removeSystem(mySystem)
        }    
    }
    engine.addSystem(mySystem)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/arquitectura/systems.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
