Sistemas
Aprenda como systems são usados para atualizar o estado da cena
As cenas do Decentraland dependem de systems para atualizar quaisquer dados ao longo do tempo, incluindo informações armazenadas no components.

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:
A função em um sistema pode realizar o que você quiser. Tipicamente, ela atuará sobre todas as entidades que atendem a certos query, seguindo certa lógica para alterar os valores armazenados nos componentes da entidade.
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.

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.
📔 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.
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.
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, 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.
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 adt maxDistance do tipo (representando).
(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 .

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

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. 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
engine.addSystem(LoopSystem) Também existe uma função de atalho e setInterval clearInterval
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
timers.clearInterval(intervalId) intervalId Onde Também existe uma função de atalho é a referência para o
retorno definido anteriormente. Custom components.
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
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 0Sistemas que não recebem uma prioridade explícita têm uma prioridade padrão de
, 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.
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()
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).
Atualizado