Entidades & Componentes
Aprenda o essencial sobre entidades e componentes em uma cena do Decentraland
As cenas da Decentraland são construídas em torno de entities, components e systems. Este é um padrão comum usado na arquitetura de diversos motores de jogo, que permite fácil composibilidade e escalabilidade.

Visão geral
Entities são a unidade básica para construir tudo nas cenas da Decentraland. Todos os objetos 3D visíveis e invisíveis e reprodutores de áudio na sua cena serão cada um uma entity. Uma entity nada mais é do que um id, que pode ser referenciado por components. A própria entity não possui propriedades ou métodos próprios, serve simplesmente para agrupar vários components.
Components definem as características de uma entity. Por exemplo, um Transform component armazena as coordenadas, rotação e escala da entity. Um MeshRenderer component dá à entity uma forma visível (como um cubo ou uma esfera) quando renderizada na cena, um Material component dá à entity uma cor ou textura. Você também pode criar components personalizados para armazenar os dados necessários da sua cena, por exemplo um custom health poderia armazenar o valor de vida restante de uma entity, e adicioná-lo a entities que representam inimigos não-jogadores em um jogo.
Se você está familiarizado com desenvolvimento web, pense em entities como o equivalente a Elements em uma DOM tree, e em components como attributes dessas elements.
No Scene Editor in Creator Hub, você pode ver os components que pertencem a uma entity selecionando-a.

📔 Nota: Em versões anteriores do SDK, Entities eram objects que eram instanciados e podiam ser estendidos para adicionar funções. A partir da versão 7.0 do SDK, entities são apenas um ID. Essa estrutura se ajusta melhor aos princípios da data oriented programming e pode ajudar no desempenho da cena.

Components como Transform, Material ou qualquer um dos shape components estão intimamente ligados à renderização da cena. Se os valores nesses components mudam, isso por si só é suficiente para o engine alterar como a cena é renderizada no próximo frame.
O engine é a parte da cena que fica no meio e gerencia todas as outras partes. Ele determina quais entities são renderizadas e como os players interagem com elas. Também coordena quais funções de systems são executadas e quando.
Components destinam-se a armazenar dados sobre a entity referenciada. Eles só podem armazenar esses dados, não podem modificar esses dados por si mesmos. Todas as alterações nos valores dos components são realizadas por Systems. Systems são completamente desacoplados dos components e das entities em si. Entities e components são agnósticos quanto ao que systems está atuando sobre eles.
Sintaxe para entities e components
O exemplo abaixo mostra algumas operações básicas para declarar e configurar entities e components básicos.
📔 Nota: Em versões anteriores do SDK, era necessário adicionar manualmente uma entity ao engine para começar a renderizá-la. A partir da versão 7 do SDK, entities são implicitamente adicionadas ao engine assim que lhes é atribuído um component.
Quando um component é criado, ele é sempre atribuído a uma entity pai. Os valores do component então afetam a entity.
Remover entities
Para remover uma entity do engine, use engine.removeEntity()
Se uma entity removida tiver quaisquer entities filhas, estas mudam seu pai de volta para a engine.RootEntity entity, que está posicionada na posição base da cena, com uma escala de 1.
Para remover uma entity e também todos os seus filhos (e quaisquer filhos dos seus filhos, recursivamente), use o removeEntityWithChildren() helper.
💡 Dica: Em vez de remover uma entity do engine, em alguns casos pode ser melhor torná-la invisível, caso você queira ser capaz de carregá-la novamente sem qualquer atraso. Veja Make invisible
Removendo entities nos bastidores
Uma entity é apenas um id que é referenciado por seus components. Então, ao remover uma entity você na verdade está removendo cada um dos components que referenciam essa entity. Isso significa que se você remover manualmente todos os components de uma entity, isso terá o mesmo efeito que fazer engine.removeEntity().
Uma vez que os components da entity são removidos, o id dessa entity fica livre para ser referenciado por novos components como uma nova entity.
Entities aninhadas
Uma entity pode ter outras entities como filhas. Graças a isso, podemos organizar entities em árvores, assim como o HTML de uma página web.

Para definir uma entity como pai de outra, a entity filha deve ter um Transform component. Você pode então definir o parent campo com uma referência para a entity pai.
Uma vez que um pai é atribuído, ele pode ser lido a partir da entity filha pelo parent campo no seu Transform component.
Se uma entity pai tiver um Transform component que afeta sua posição, escala ou rotação, suas entities filhas também são afetadas. Qualquer valor de posição ou rotação é somado, quaisquer valores de escala são multiplicados.
Se tanto a entity pai quanto a filha não tiverem um Transform component, os seguintes valores padrão são usados.
Para position, o centro do pai é 0, 0, 0
Para rotation a rotação do pai é o quaternion 0, 0, 0, 1 (equivalente aos ângulos Euler 0, 0, 0)
Para scale, o pai é considerado ter um tamanho de 1. Qualquer redimensionamento do pai afeta escala e posição proporcionalmente.
Entities sem component de shape são invisíveis na cena. Estas podem ser usadas como recipientes para manipular e posicionar múltiplas entities como um grupo.
Para separar uma entity filha de seu pai, você pode atribuir o pai da entity para engine.RootEntity.
📔 Nota: Ao lidar com entities aninhadas que são sincronizadas com outros players, use a parentEntity() função em vez da parent entity no Transform. Veja Parented entities
No Scene Editor, você pode ver toda a hierarquia de entities aninhadas na sua cena no painel lateral esquerdo.

Obter uma entity por ID
Cada entity na sua cena tem um número único id. Você pode recuperar um component que se refere a uma entity específica do engine com base nesse ID.
📔 Nota: Os ids de entity entre 0 e 511 são reservados pelo engine para entities fixas, como o avatar do player, a base da cena, etc.
Por exemplo, se o clique de um player ou um raycast atinge uma entity, isso retornará o id da entity atingida, e você pode usar o comando acima para buscar o Transform component da entity que corresponde àquele id. Você também pode buscar qualquer outro component dessa entity da mesma forma.
Obter uma entity por nome
Ao adicionar entities via arrastar-e-soltar no Scene Editor, cada entity tem um nome único. Use a engine.getEntityOrNullByName() função para referenciar uma dessas entities a partir do seu código. Passe o nome da entity como uma string, conforme escrito na UI do Scene Editor, na visualização em árvore à esquerda.
📔 Nota: Certifique-se de usar engine.getEntityOrNullByName() apenas dentro da main() função, em funções que rodem após main(), ou em um system. Se usado fora de um desses contextos, as entities criadas na UI do Scene Editor podem ainda não estar instanciadas.
Você pode realizar qualquer ação em uma entity buscada via este método, como adicionar ou remover components, modificar valores de components existentes ou remover a entity do engine.
Todas as entities adicionadas via a UI do Scene Editor têm um Name component, você pode iterar sobre todas elas assim:
Adicionar ou substituir um component
Cada entity pode ter apenas um component de um determinado tipo. Por exemplo, se você tentar atribuir um Transform a uma entity que já tem um, isso causará um erro.
Para evitar esse erro, você pode usar .createOrReplace em vez de .create. Este comando sobrescreve quaisquer components existentes do mesmo tipo se existirem, caso contrário cria um novo component assim como .create.
📔 Nota: Como .createOrReplace executa uma checagem adicional antes de criar o component, é sempre mais performático usar .create. Se você tem certeza de que a entity não possui já um component como o que você está adicionando, use .create.
Acessar um component a partir de uma entity
Você pode acessar os components de uma entity usando o .get() da entity ou as funções getMutable()
let transform = Transform.getMutable(box) A get()
função busca uma referência apenas de leitura ao component. Você não pode alterar quaisquer valores a partir dessa referência do component. ou as funções Se você deseja alterar os valores do component, use a função
em vez disso. Se você alterar os valores na versão mutável do component, você estará afetando diretamente a entity à qual esse component pertence. Veja mutable data
📔 Notapara mais detalhes. ou as funções : Use Aapenas se você realmente for fazer alterações nos valores do component. Caso contrário, sempre use data oriented programming. Esta prática segue os princípios de
transform.scale.x = 5 O exemplo acima modifica diretamente o valor da x
scale no component Transform. Se você não tem certeza se a entity realmente possui o component que você está tentando recuperar, use getOrNull() ou.
📔 NotagetMutableOrNull() Se você não tem certeza se a entity realmente possui o component que você está tentando recuperar, use getOrNull() ou : Evite usar .get() e ou as funções.
const mutableTransformOrNull = Transform.getMutableOrNull(myEntity)
Aeou as funçõesSe o component que você está tentando recuperar não existir na entity:Se você não tem certeza se a entity realmente possui o component que você está tentando recuperar, useeouretorna um erro.retorna.
Null
Remover um component de uma entity Para remover um component de uma entity, use o deleteFrom()
Transform.deleteFrom(myEntity)
📔 NotaSe você tentar remover um component que não existe na entity, essa ação não gerará erros. : Para remover todos os components de uma entity de uma vez, veja
esta seção
Verificar um component Você pode verificar se uma entity possui uma instância de certo component usando a função has() . Esta função retorna true se o component estiver presente, e false
💡 Dicaconst hasTransform = Transform.has(myEntity) : Você também pode query components Você pode verificar se uma entity possui uma instância de certo component usando a funçãopara buscar uma lista completa de entities que possuem um component específico, ou um conjunto específico de components. Não itere manualmente por todas as entities na cena para verificar cada uma com um
, essa abordagem é muito menos eficiente.
Verificar mudanças em um component Use a função onChange
para executar uma função de callback sempre que os valores do component mudarem para uma dada entity. Isso funciona em qualquer component, e é um ótimo atalho para manter seu código legível.
console.log('Cube visibility changed: ', newVisibilityComponent.visible) Se o component for removido da entity, então a função é chamada com uma entrada de.
📔 Notaundefined : A função .onChange() atualmente só funciona com components nativos do SDK, não funciona com custom comopnents
definidos pelo criador.
Obter todas as entities descendentes Ao trabalhar com hierarquias de entities aninhadas, você pode precisar acessar todas as entities que são descendentes de uma entity pai, independentemente de quão profundamente aninhadas estejam. Para isso você pode usargetEntitiesWithParent . Ela recebe como argumentos o engine parent e a
entity e retorna uma lista de todas as entities que têm aquela entidade específica como seu pai. Isso é especialmente útil quando você precisa encontrar entities que podem estar aninhadas sob vários níveis abaixo de uma entity pai. Em vez de percorrer manualmente a hierarquia nível por nível, getEntitiesWithParent()
// processar cada entity filha Você talvez queira usar a funçãogetComponentEntityTree()
let transform = Transform.getMutable(box) console.log('Descendant position:', transform.position) getComponentEntityTree
. Ela recebe como argumentos ofunção aceita três parâmetros:: A instância do engine que executa as entitiesentity: A entity raiz para começarcomponentTransform: O component para filtrar (tipicamente
para hierarquias espaciais)
A função retorna um generator que produz cada entity descendente na estrutura em árvore. Apenas entities que tenham o component especificado serão incluídas nos resultados.
console.log('Found target entity:', descendantEntity)
Entities reservadas
engine.RootEntityCertos ids de entity são reservados para entities especiais que existem em toda cena. Eles podem ser acessados através dos seguintes aliases:engine.PlayerEntity
📔 Notaengine.CameraEntity main() : Evite referir-se a essas entities antes que elas estejam inicializadas. Para evitar esse problema, refira-se a essas entities na
função, ou em um system.
A entity raiz engine.RootEntityTodas as entities na cena são filhas da
, direta ou indiretamente. Esta entity não possui um component Transform, mas é usada para gerenciar vários components que representam configurações mais globais, como, skybox controlcursor position , ou.
screen dimensions
let transform = Transform.getMutable(box) Certos ids de entity são reservados para entities especiais que existem em toda cena. Eles podem ser acessados através dos seguintes aliases: A entity do player
entity representa o avatar do player. Transform Busque o component do player para obter a posição e rotação atuais do player, vejauser data . O Transform do player é somente leitura; para modificá-lo use a função movePlayerTo() ,.
saiba mais Você também pode anexar objetos ao player definindo-os como filhos dessa entity, embora o Attach to Player
seja frequentemente a opção melhor para isso.
let transform = Transform.getMutable(box) engine.PlayerEntity A entity da câmera
entity representa a câmera do player. Transform Busque o component da câmera para obter a posição e rotação da câmera. O Transform desta entity também é somente leitura. Para modificar o ângulo ou posição da câmera, use uma.
Virtual camera Você também pode buscar o CameraMode component da câmera para saber se o player está usando o modo de câmera em 1ª ou 3ª pessoa, veja.
Atualizado