# Systems

As cenas do Decentraland dependem de *systems* para atualizar quaisquer dados ao longo do tempo, incluindo informações armazenadas no [components](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/architecture/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)

*systems* são o que torna as cenas dinâmicas, são funções executadas periodicamente a cada tick do laço de jogo da cena, alterando o que será renderizado.

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

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

A função em um sistema pode realizar o que você quiser. Tipicamente, ela atuará sobre todas as entidades que atendem a certos [query](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/architecture/querying-components.md), seguindo certa lógica para alterar os valores armazenados nos componentes da entidade.

```ts
function moveSystem(dt: number) {
  // iterar sobre todas as entidades 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 sistema `MoveSystem` é uma função que é executada em cada tick do laço de jogo, alterando a posição de toda entidade na cena que possui 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)

Você pode ter múltiplos sistemas na sua cena para desacoplar comportamentos diferentes, deixando seu código mais limpo e mais fácil de escalar e reutilizar. Por exemplo, um sistema pode lidar com a física, outro pode fazer uma entidade obstáculo se mover para frente e para trás continuamente, outro pode lidar com a IA dos personagens.

Múltiplos sistemas podem agir sobre uma única entidade. Por exemplo, um personagem não jogador pode se mover por conta própria com base em uma IA, mas também ser afetado pela gravidade ao caminhar acidentalmente de um penhasco. Nesse cenário, os sistemas de física e de IA nem precisam saber um do outro. Eles reavaliam independentemente seu estado atual a cada tick do laço de jogo e implementam sua própria lógica separada.

## A função do sistema

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

Em uma cena do Decentraland, você pode pensar no laço de jogo como a agregação de todas as funções de sistema da sua cena.

{% hint style="warning" %}
**📔 Nota**: Se você adicionar múltiplas instâncias do mesmo sistema ao engine, a função será executada múltiplas vezes por tick do laço de jogo. Por exemplo, adicionar um sistema duas vezes poderia resultar em uma entidade se movendo com o dobro da velocidade esperada, pois ela avançaria dois incrementos a cada tick.
{% endhint %}

## Manipular entidades por referência

Alguns componentes e sistemas são destinados a ser usados apenas em uma entidade na cena. Por exemplo, em uma entidade que armazena a pontuação de um jogo ou talvez um portão principal que é único na cena. Para acessar uma dessas entidades dentro de um sistema, você pode simplesmente referir-se à entidade ou aos seus componentes pelo nome nas funções do sistema.

```ts
export function main(){
	// criar uma nova entidade
	const game = engine.addEntity()

	// adicionar componente a essa entidade
	ScoreComponent.create(game)
}

// Defina o sistema
export function UpdateScore() {

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

// Adicionar sistema ao engine
engine.addSystem(UpdateScore)
```

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

## Iterar sobre uma consulta de componente

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

Você não quer que a função de um sistema itere sobre *o conjunto inteiro* de entidades na cena, pois isso poderia ser muito custoso em termos de poder de processamento. Para evitar isso, você pode [consultar componentes](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/architecture/querying-components.md), para iterar apenas sobre as entidades relevantes.

Por exemplo, sua cena pode ter um `PhysicsSystem` que calcula o efeito da gravidade sobre as entidades da sua cena. Algumas entidades na sua cena, como árvores, não devem se mover; então seria inteligente evitar calcular os efeitos da gravidade nelas. Você pode definir um `HasPhysics` componente para marcar entidades que poderiam ser afetadas pela gravidade, e então ter `PhysicsSystem` lidando apenas com as entidades retornadas por essa query.

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

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

  // Calcular efeito da física
  }
}

// Adicionar sistema ao engine
engine.addSystem(PhysicsSystem)
```

## Tempo delta entre frames

A função em um sistema pode opcionalmente incluir um argumento chamado `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a`dt `maxDistance` do tipo *(representando*).

```ts
delta time

  function MySystem(dt: number) {
  // Atualizar cena
}

console.log("tempo desde o último tick: ", dt)
```

*(representando* engine.addSystem(MySystem)

representa o tempo que passou desde o último tick do laço de jogo, em segundos. `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a` As cenas do Decentraland são atualizadas por padrão a 30 ticks por segundo. Isso significa que o *1/30* (0.0333...).

argumento passado a todos os sistemas tenderá a ser igual a `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a` Se o processamento de um frame levar menos tempo do que esse intervalo, então o engine aguardará o tempo restante para manter as atualizações com ritmo regular e *1/30* .

![](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)

permanecerá igual a *1/30* Se o processamento de um frame demorar mais do que *1/30* segundos, a renderização desse frame é atrasada. O engine então tenta terminar esse frame e exibí-lo o mais rápido possível. Em seguida, procede para o próximo frame e tenta mostrá-lo

![](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)

segundos após o último frame. Ele não compensa pelo atraso anterior.

O `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a` Idealmente, você deve evitar que 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 existe a possibilidade, então sua cena deve estar preparada para lidar com isso de forma graciosa.

Veja [a variável é útil quando o processamento de frames excede o tempo padrão. Pressuponto 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.](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/3d-essentials/entity-positioning.md) posicionamento de entidades `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a` para exemplos de como usar

## para tornar o movimento mais suave.

Loop em um intervalo de tempo `O exemplo acima executa um raycast recorrente a cada 0,1 segundos. Ele usa um componente timer e a` Se você quer que um sistema execute algo em um intervalo de tempo regular, você pode fazer isso combinando o

```ts
argumento com um temporizador.

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

// FAÇA ALGO
```

engine.addSystem(LoopSystem) `Também existe uma função de atalho` e `setInterval` clearInterval

```ts
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 tempo.
    const intervalId = timers.setInterval(() => {
}, 10000)
```

console.log('Imprimindo isso a cada 10 segundos') `Onde o primeiro argumento,`callback `console.log()`, é a função a ser executada (neste caso, o `), e o segundo argumento,`ms

(1000 neste caso), são os milissegundos a aguardar entre cada execução da função. `Também existe uma função de atalho` function, `setInterval` Para parar o

```
é usado.
```

timers.clearInterval(intervalId) `intervalId` Onde `Também existe uma função de atalho` é a referência para o

retorno definido anteriormente. [Custom components](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/architecture/custom-components.md).

## Para casos de uso mais complexos, onde podem haver múltiplos atrasos e loops sendo criados dinamicamente, pode valer a pena definir um componente personalizado para armazenar um valor de temporizador individual para cada entidade. Veja

Ordem de execução dos sistemas

Em alguns casos, quando você tem múltiplos sistemas em execução, pode importar qual sistema é executado primeiro pela sua cena. *Por exemplo, você pode ter um* physics *sistema que atualiza a posição das entidades na cena, e outro* boundaries *sistema que atualiza a posição das entidades na cena, e outro* sistema que garante que nenhuma das entidades esteja posicionada fora dos limites da cena. Nesse caso, você quer garantir que o sistema *Por exemplo, você pode ter um* seja executado por último. Caso contrário, o sistema *sistema que atualiza a posição das entidades na cena, e outro* poderia mover entidades para fora dos limites da cena, mas o sistema

não descobriria até ser executado novamente no próximo frame. `Ao adicionar um sistema ao engine, defina um campo opcional` priority

```ts
para determinar quando o sistema é executado em relação a outros sistemas.
engine.addSystem(PhysicsSystem, 1)
```

engine.addSystem(BoundariesSystem, 5) *1* Sistemas com um número de prioridade menor são executados primeiro, então um sistema com prioridade *5*.

é executado antes de um com prioridade *0*Sistemas que não recebem uma prioridade explícita têm uma prioridade padrão de

&#x20;, portanto esses são executados primeiro.

## Se dois sistemas têm o mesmo número de prioridade, não há como saber com certeza qual deles será executado primeiro.

Remover um sistema

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

Se um sistema é definido mas não é adicionado ao engine, sua função não é chamada pelo engine.

```ts
Para remover um sistema, você deve primeiro dar-lhe um nome ao adicioná-lo ao engine, para que você possa referir-se ao sistema mais tarde.
// declarar sistema
  function mySystem(dt: number){
}

console.log("tempo desde o último tick: ", dt)
// adicionar sistema (dando-lhe uma prioridade e nome)

engine.addSystem(mySystem, 1, "DelaySystem")
// remover sistema
```

engine.removeSystem("DelaySystem")

Uma cena pode potencialmente ter múltiplas instâncias do mesmo sistema rodando juntas, então você precisa dizer ao engine qual delas remover. `Outra forma de deletar um sistema é declarar um ponteiro para o sistema e então passar esse ponteiro para o` engine.removeSystem()

```ts
Para remover um sistema, você deve primeiro dar-lhe um nome ao adicioná-lo ao engine, para que você possa referir-se ao sistema mais tarde.
// declarar sistema
  function mySystem(dt: number){
}

método.
// adicionar sistema (criando um ponteiro)

engine.addSystem(mySystem, 1, "DelaySystem")
const mySystemInstance = engine.addSystem(mySystem)
```

engine.removeSystem(mySystemInstance) *Observe que o ponteiro é para a* instance `Outra forma de deletar um sistema é declarar um ponteiro para o sistema e então passar esse ponteiro para o` do sistema, não para a classe do sistema. No exemplo acima, `não está sendo passado` mySystem `(a declaração da classe do sistema). Está sendo passado` mySystemInstance

(a instância que foi adicionada ao engine).

```ts
   Você pode usar o método abaixo para fazer um sistema se auto-terminar quando seu propósito estiver completo.
        const mySystem = function(dt: number){
        time += dt
		if(time > 3){","}
        }    
    }
    engine.addSystem(mySystem)
```
