> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/escenas-sdk7/arquitectura/systems.md).

# Systems

Las escenas de Decentraland dependen de *systems* para actualizar cualquier dato con el tiempo, incluida la información almacenada en el [components](/creator/content-creator-es/escenas-sdk7/arquitectura/entities-components.md).

![](/files/f8ae24ca96098f4c403470a24f18af76952e3f4c)

*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:

```ts
// Define el sistema
function mySystem() {
  console.log("Se ejecuta en cada tick. Mi sistema está corriendo")
}
// Agrega el sistema al engine
engine.addSystem(mySystem)
```

La función de un sistema puede hacer lo que quieras. Normalmente, actuará sobre todas las entidades que cumplan ciertos [criterios de consulta](/creator/content-creator-es/escenas-sdk7/arquitectura/querying-components.md), siguiendo cierta lógica para cambiar los valores almacenados en los componentes de la entidad.

```ts
function moveSystem(dt: number) {
  // iterar sobre todas las entidades con un Transform
  for (const [entity] of engine.getEntitiesWith(Transform)) {

  // obtener un componente Transform mutable
  const transform = Transform.getMutable(entity)

  // actualizar el valor de la posición
    transform.position.z += 0.01
  }
}

engine.addSystem(moveSystem)
```

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.

![](/files/83b06b1db5e34978d664e015635a62c013905046)

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.

{% hint style="warning" %}
**📔 Nota**: No puedes agregar la misma función de sistema al engine más de una vez. Si intentas agregar un sistema que ya fue agregado, el engine lanza un error: `System "<name>" ya se agregó al engine`.
{% endhint %}

## 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.

```ts
// declara la referencia de la entidad en el alcance del módulo para que los sistemas puedan acceder a ella
let game: Entity

export function main(){
	// crea una nueva entidad
	game = engine.addEntity()

	// agrega un componente a esa entidad
	ScoreComponent.create(game)
}

// Define el sistema
export function UpdateScore() {

  // llama a la referencia de la entidad individual
  const points = ScoreComponent.get(game).points
  console.log(points)
}

// Agrega el sistema al engine
engine.addSystem(UpdateScore)
```

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](/creator/content-creator-es/escenas-sdk7/arquitectura/querying-components.md), 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.

```ts
// Define el sistema
export function PhysicsSystem() {
  // iterar sobre todas las entidades con un HasPhysics
  for (const [entity] of engine.getEntitiesWith(HasPhysics)) {

  // obtener un componente Transform mutable
  const transform = Transform.getMutable(entity)

  // Calcula el efecto de la física
  }
}

// Agrega el sistema al engine
engine.addSystem(PhysicsSystem)
```

## Tiempo delta entre frames

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

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

  // Actualiza la escena
  console.log("tiempo desde el último tick: ", dt)
}

engine.addSystem(MySystem)
```

*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...).

![](/files/4fe56eb9625a84e51e85f23ed1e14de4a01500e9)

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.

![](/files/8f0cfedaf4c0d5bd4feb7ac252b368c6448116a3)

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](/creator/content-creator-es/escenas-sdk7/conceptos-basicos-de-contenido-3d/entity-positioning.md) 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.

```ts
let timer: number = 10

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

engine.addSystem(LoopSystem)
```

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.

```ts
import { timers } from '@dcl/sdk/ecs'

const intervalId = timers.setInterval(() => {
    console.log('Imprimiendo esto cada 10 segundos')
}, 10000)
```

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.

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

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](/creator/content-creator-es/escenas-sdk7/arquitectura/custom-components.md).

## 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.

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

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.

```ts
// declara el sistema
function mySystem(dt: number){
  console.log("retraso desde el último tick: ", dt)
}

// agrega el sistema (dándole una prioridad y un nombre)
engine.addSystem(mySystem, 1, "DelaySystem")

// elimina el sistema
engine.removeSystem("DelaySystem")
```

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.

```ts
// declara el sistema
function mySystem(dt: number){
  console.log("retraso desde el último tick: ", dt)
}

// agrega el sistema
engine.addSystem(mySystem)

// elimina el sistema pasando su función
engine.removeSystem(mySystem)
```

`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.

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
