# Systems

As cenas de 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).

![](/files/d62829da4dc69be10b0d3103c853468fef617c91)

*systems* são o que tornam as cenas dinâmicas; são funções executadas periodicamente a cada tick do game loop da cena, 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 em cada tick. O meu system está em execução")
}
// Adicione o 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 certas [query](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md), seguindo uma lógica específica para alterar os valores armazenados nos components da entity.

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

  // buscar 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 executa a cada tick do game loop, alterando a posição de cada entity na cena que possui um Transform.

![](/files/848af8ae25acc1f2a34c2c6b3ab110f68eb05dbd)

Você pode ter vários systems na sua cena para desacoplar comportamentos diferentes, tornando o seu código mais limpo e mais fácil de escalar e reutilizar. Por exemplo, um system pode lidar com a física, outro pode fazer uma entity obstáculo mover-se para frente e para trás continuamente, outro pode lidar com a IA dos personagens.

Vários systems podem atuar sobre uma única entity. Por exemplo, um personagem não-jogador pode mover-se por conta própria com base em uma IA, mas também ser afetado pela gravidade ao caminhar acidentalmente para fora de um penhasco. Nesse cenário, os systems de física e de IA nem sequer precisam saber da existência um do outro. Eles reavaliam independentemente o seu estado atual a cada tick do game loop e implementam a 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 lugar nenhum no seu código.

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

{% hint style="warning" %}
**📔 Nota**: Se você adicionar várias instâncias de um mesmo system ao engine, a função será executada várias vezes por tick do game loop. Por exemplo, adicionar um system duas vezes pode fazer com que uma entity se mova ao dobro da velocidade esperada, à medida que avança dois incrementos em cada tick.
{% endhint %}

## Trate entities por referência

Alguns components e systems destinam-se a ser usados apenas em uma entity na cena. Por exemplo, em uma entity que armazena a pontuação de um jogo ou talvez um portão principal que seja único na cena. 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
export function main(){
	// criar uma nova entity
	const game = engine.addEntity()

	// adicionar component àquela entity
	ScoreComponent.create(game)
}

// Defina o system
export function UpdateScore() {

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

// Adicione o 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 query de component

Muitas vezes, a sua cena 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 jogador. Faz sentido lidar com todas essas entities semelhantes em um único system, iterando sobre a lista e executando 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 cena, pois isso pode ser muito custoso em termos de poder 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, a sua cena pode ter um `PhysicsSystem` que calcula o efeito da gravidade sobre as entities da sua cena. Algumas entities na sua cena, como árvores, não devem se mover nunca; então seria inteligente evitar calcular os efeitos da gravidade sobre elas. Você pode definir um component `HasPhysics` para marcar entities que podem ser afetadas pela gravidade, e então ter `PhysicsSystem` lidar apenas com as entities retornadas por esta query.

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

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

  // Calcular o efeito da física
  }
}

// Adicione o 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 cena
  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.

As cenas de Decentraland são atualizadas por padrão a 30 ticks por segundo. Isso significa que o `dt` argumento passado para todos os systems tenderá a ser igual a *1/30* (0.0333...).

Se o processamento de um frame levar menos tempo do que esse intervalo, então o engine esperará o tempo restante para manter as atualizações com ritmo regular e `dt` permanecerá igual a *1/30* .

![](/files/2e8df1ad33dc93fdb5f155242442eaed4c329bc0)

Se o processamento de um frame demorar mais do que *1/30* segundos, o desenho desse frame é atrasado. O engine então tenta concluir esse frame e mostrá-lo assim que possível. Em seguida, prossegue para o próximo frame e tenta mostrá-lo *1/30* segundos após o último frame. Ele não compensa o atraso anterior.

![](/files/1e6dbafbc8610d229544a3f78005853a9c8e58ee)

Idealmente, você deve evitar que a sua cena perca frames, pois isso impacta a qualidade da experiência do jogador. Como isso depende do poder de processamento da máquina do jogador, é sempre possível que a sua cena precise estar pronta para lidar com isso com elegância.

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, de modo que a taxa de mudança pareça constante e proporcional ao atraso entre frames.

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

## Iterar 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 argumento `dt` com um timer.

```ts
let timer: number = 10

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

engine.addSystem(LoopSystem)
```

Há também 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 determinada função a cada X quantidade de tempo.

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

Onde o primeiro argumento, `callback`, é a função a ser executada (neste caso, a `console.log()`), e o segundo argumento, `ms`(1000 neste caso), é a quantidade de milissegundos a esperar entre cada execução da função.

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

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

Onde `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 dos systems

Em alguns casos, quando você tem vários systems em execução, pode importar-se com qual system é executado primeiro pela sua cena.

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

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

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

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

Systems que não recebem uma prioridade explícita têm uma prioridade padrão de *0*, então estes são executados primeiro.

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á-la ou desligá-la.

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

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

```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")
```

Uma cena pode potencialmente ter várias instâncias de um mesmo system em execução juntas, então você precisa dizer ao engine qual delas remover.

Outra maneira de deletar um system é declarar um ponteiro para o system e depois passar esse ponteiro para o `engine.removeSystem()` método.

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

// adicionar system (criando um ponteiro)
const mySystemInstance = engine.addSystem(mySystem)

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

Note que o ponteiro é para a *instância* do system, não para a classe do system. No exemplo acima, `engine.removeSystem()` não está sendo passado `mySystem` (a declaração da classe do system). Está sendo passado `mySystemInstance` (a instância que foi adicionada ao engine).

Você pode usar o método abaixo para fazer um system encerrar a si mesmo quando o seu propósito estiver 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-pt/scenes-sdk7/arquitetura/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.
