> 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-pt/scenes-sdk7/arquitetura/systems.md).

# Systems

Saiba como os systems são usados para atualizar o estado da scene

As scenes do Decentraland dependem de *systems* para atualizar quaisquer dados ao longo do tempo, incluindo informações armazenadas em cada [components](/creator/content-creator-pt/scenes-sdk7/arquitetura/entities-components.md).

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-de62a18d51b28bebd55c86e8ef5a8a783467ae62%2Fecs-big-picture.png?alt=media\&token=0d7a02a2-955a-44ed-ae77-5df99c49e530)

*systems* são o que tornam as scenes dinâmicas; são funções executadas periodicamente a cada tick do game loop da scene, alterando o que será renderizado.

O exemplo a seguir mostra uma declaração básica de system:

```ts
// Defina o system
function mySystem() {
  console.log("Executado a cada tick. Meu system está em execução")
}
// adicionar system ao engine
engine.addSystem(mySystem)
```

A função em um system pode fazer qualquer coisa que você quiser. Normalmente, ela atuará sobre todas as entities que atendem a certos [query](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md), seguindo certa lógica para alterar os valores armazenados nos components da entity.

```ts
function moveSystem(dt: number) {
  // iterar sobre todas as entities com um Transform
  for (const [entity] of engine.getEntitiesWith(Transform)) {

  // obter um componente Transform mutável
  const transform = Transform.getMutable(entity)

  // atualizar o valor da posição
    transform.position.z += 0.01
  }
}

engine.addSystem(moveSystem)
```

No exemplo acima, o system `MoveSystem` é uma função que roda a cada tick do game loop, alterando a posição de cada entity na scene que tem um Transform.

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-826c0dcfcfc5a6d5719de5a0939214a534078567%2Fecs-system-new.png?alt=media\&token=59a83c9e-0d01-454b-bd5e-4ca61779a3f3)

Você pode ter vários systems na sua scene para desacoplar comportamentos diferentes, tornando seu código mais limpo e mais fácil de escalar e reutilizar. Por exemplo, um system pode lidar com physics, outro pode fazer uma entity de obstacle se mover para frente e para trás continuamente, outro pode lidar com a AI dos characters.

Vários systems podem agir sobre uma única entity. Por exemplo, um personagem não jogador pode se mover por conta própria com base em uma AI, mas também ser afetado pela gravidade ao andar acidentalmente para fora de um penhasco. Nessa situação, os systems de physics e de AI nem precisam saber um do outro. Eles reavaliam independentemente seu estado atual a cada tick do game loop e implementam sua própria lógica separada.

## A função do system

A função de um system é executada periodicamente, uma vez a cada tick do game loop. Isso acontece automaticamente; você não precisa chamar explicitamente essa função de nenhum lugar no seu código.

Em uma scene do Decentraland, você pode pensar no game loop como a agregação de todas as funções de system na sua scene.

{% hint style="warning" %}
**📔 Observação**: Você não pode adicionar a mesma função de system ao engine mais de uma vez. Se tentar adicionar um system que já foi adicionado, o engine lança um erro: `System "<name>" já adicionado ao engine`.
{% endhint %}

## Manipular entities por referência

Alguns components e systems devem ser usados apenas em uma entity na scene. Por exemplo, em uma entity que armazena a pontuação de um jogo ou talvez um portão principal que é único na scene. Para acessar uma dessas entities dentro de um system, você pode simplesmente referir-se à entity ou aos seus components pelo nome nas funções do system.

```ts
// declarar a referência da entity no escopo do módulo para que systems possam acessá-la
let game: Entity

export function main(){
	// criar uma nova entity
	game = engine.addEntity()

	// adicionar component a essa entity
	ScoreComponent.create(game)
}

// Defina o system
export function UpdateScore() {

  // chamar a referência da entity individual
  const points = ScoreComponent.get(game).points
  console.log(points)
}

// adicionar system ao engine
engine.addSystem(UpdateScore)
```

Para projetos maiores, recomendamos que você mantenha as definições de system em arquivos separados da instanciação de entities e components.

## Iterar sobre uma component query

Muitas vezes, sua scene terá várias entities do mesmo tipo que terão comportamentos semelhantes. Por exemplo, muitas portas que podem ser abertas, ou muitos inimigos que podem atacar o player. Faz sentido lidar com todas essas entities semelhantes em um único system, iterando sobre a lista e realizando as mesmas verificações em cada uma.

Você não quer que a função de um system itere sobre *todo o* conjunto de entities na scene, pois isso pode ser muito custoso em termos de processamento. Para evitar isso, você pode [consultar components](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md), para iterar apenas sobre as entities relevantes.

Por exemplo, sua scene pode ter um `PhysicsSystem` que calcula o efeito da gravidade sobre as entities da sua scene. Algumas entities na sua scene, como árvores, não devem se mover nunca; então seria inteligente evitar calcular os efeitos da gravidade sobre elas. Você pode definir um `HasPhysics` component para marcar entities que podem ser afetadas pela gravidade e, então, fazer com que `PhysicsSystem` trate apenas as entities retornadas por esta query.

```ts
// Defina o system
export function PhysicsSystem() {
  // iterar sobre todas as entities com um HasPhysics
  for (const [entity] of engine.getEntitiesWith(HasPhysics)) {

  // obter um componente Transform mutável
  const transform = Transform.getMutable(entity)

  // calcular o efeito da physics
  }
}

// adicionar system ao engine
engine.addSystem(PhysicsSystem)
```

## Delta time entre frames

A função em um system pode opcionalmente incluir um argumento chamado `dt`, do tipo `number` (representando *delta time*).

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

  // atualizar a scene
  console.log("tempo desde o último tick: ", dt)
}

engine.addSystem(MySystem)
```

*delta time* representa o tempo que passou desde o último tick do game loop, em segundos.

O `dt` o argumento é o tempo real decorrido desde o último tick do game loop, medido em segundos. O SDK não impõe uma taxa de tick fixa: o host runtime passa esse valor, e ele varia com o framerate da scene.

Quanto mais suave uma scene roda, mais frequentemente os ticks ocorrem e menor é cada `dt` valor. Quando um tick leva mais tempo para ser processado, passa mais tempo antes do próximo e `dt` cresce de acordo.

Essa taxa de frames do lado da scene tem limite de 30 ticks por segundo, caso em que o valor de `dt` é *1/30* (0.0333...).

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-9ebcec63913c57ddf96107a817b14797211c1de2%2Fecs-framerate.png?alt=media\&token=3493a280-5778-492f-afc5-e98b45d6beb6)

Quando o processamento de um frame leva mais tempo, a renderização desse frame é atrasada, e o `dt` passado no próximo tick reflete esse intervalo maior. O engine não compensa o atraso retroativamente; `dt` sempre informa o tempo real decorrido para que seus systems possam se ajustar a ele.

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-951edc3e7611eb138145de377ec07dfc8ec4836b%2Fecs-framerate-heavy.png?alt=media\&token=e3656977-e7aa-4f14-854b-e9071ed18b02)

Idealmente, você deve evitar que sua scene perca frames, pois isso afeta a qualidade da experiência do player. Como isso depende da capacidade de processamento da máquina do player, sempre existe a possibilidade de que sua scene precise estar pronta para lidar com isso de forma graciosa.

O `dt` a variável é útil quando o processamento do frame excede o tempo padrão. Assumindo que o frame atual levará tanto tempo quanto o anterior, essa informação pode ser usada para calcular quanto ajustar uma mudança gradual, para que a taxa de mudança pareça constante e proporcional ao atraso entre frames.

Veja [posicionamento de entities](/creator/content-creator-pt/scenes-sdk7/fundamentos-de-conteudo-3d/entity-positioning.md) para exemplos de como usar `dt` para tornar o movimento mais suave.

## Loop em um intervalo de tempo

Se você quiser que um system execute algo em um intervalo de tempo regular, você pode fazer isso combinando o `dt` argumento com um timer.

```ts
let timer: number = 10

function LoopSystem(dt: number) {
  timer -= dt
  if (timer <= 0) {
      timer = 10
      // FAÇA ALGUMA COISA
    }
}

engine.addSystem(LoopSystem)
```

Também há uma função de atalho `setInterval` e `clearInterval` que usa Systems em segundo plano. Isso permite uma versão mais fácil e curta quando a intenção é executar uma certa função a cada X unidades de tempo.

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

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

Em que o primeiro argumento, `callback`, é a função a ser executada (neste caso, o `console.log()`), e o segundo argumento, `ms`(10000 neste caso), são os milissegundos de espera entre cada execução da função.

Para parar o `setInterval` function, `clearInterval` é usado.

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

Em que `intervalId` é a referência ao `setInterval` return definido anteriormente.

Para casos de uso mais complexos, em que pode haver vários atrasos e loops sendo criados dinamicamente, pode valer a pena definir um component personalizado para armazenar um valor de timer individual para cada entity. Veja [Custom components](/creator/content-creator-pt/scenes-sdk7/arquitetura/custom-components.md).

## Ordem de execução do system

Em alguns casos, quando você tem vários systems em execução, talvez se importe com qual system é executado primeiro pela sua scene.

Por exemplo, você pode ter um *physics* system que atualiza a posição de entities na scene, e outro *boundaries* system que garante que nenhuma das entities seja posicionada fora dos limites da scene. Nesse caso, você quer garantir que o *boundaries* system seja executado por último. Caso contrário, o *physics* system poderia mover entities para fora dos limites da scene, mas o *boundaries* system não descobrirá até ser executado novamente no próximo frame.

Ao adicionar um system ao engine, defina um `prioridade` campo opcional para determinar quando o system é executado em relação aos outros systems.

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

Systems com um número de prioridade mais alto são executados primeiro, então um system com prioridade de *5* é executado antes de um de prioridade *1*.

Systems que não recebem uma prioridade explícita têm uma prioridade padrão de *100000*. Como números maiores executam primeiro, esses systems são executados antes daqueles com uma prioridade explícita menor.

Se dois systems tiverem o mesmo número de prioridade, não há como saber com certeza qual deles será executado primeiro.

## Remover um system

Uma instância de um system pode ser adicionada ou removida do engine para ligá-lo ou desligá-lo.

Se um system for definido, mas não for adicionado ao engine, sua função não será chamada pelo engine.

Para remover um system, você deve primeiro dar um nome a ele ao adicioná-lo ao engine, para que possa se referir ao system depois.

```ts
// declarar system
function mySystem(dt: number){
  console.log("atraso desde o último tick: ", dt)
}

// adicionar system (dando a ele uma prioridade e um nome)
engine.addSystem(mySystem, 1, "DelaySystem")

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

A string que você passa para `engine.removeSystem()` deve corresponder ao nome que você atribuiu ao system quando o adicionou.

Outra forma de remover um system é passar a própria função do system para o `engine.removeSystem()` método. Dessa forma, você não precisa dar um nome ao system ao adicioná-lo.

```ts
// declarar system
function mySystem(dt: number){
  console.log("atraso desde o último tick: ", dt)
}

// adicionar system
engine.addSystem(mySystem)

// remover system passando sua função
engine.removeSystem(mySystem)
```

`engine.removeSystem()` aceita tanto a string de nome que você atribuiu ao adicionar o system quanto uma referência à própria função do system.

Você pode usar o método abaixo para fazer um system se encerrar sozinho quando seu propósito estiver completo.

```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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/arquitetura/systems.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
