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.

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:
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, seguindo certa lógica para alterar os valores armazenados nos components da entity.
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.

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.
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.
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, 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.
Delta time entre frames
A função em um system pode opcionalmente incluir um argumento chamado dt, do tipo number (representando delta time).
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...).

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.

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