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 systemsarrow-up-right. 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 Hubarrow-up-right, você pode ver os components que pertencem a uma entity selecionando-a.


circle-exclamation


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 systemsarrow-up-right 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 Systemsarrow-up-right. 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.

circle-exclamation

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.

circle-info

💡 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 invisiblearrow-up-right

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.

circle-exclamation

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.

circle-exclamation

Por exemplo, se o clique de um player ou um raycastarrow-up-right 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.

circle-exclamation

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.

circle-exclamation

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. Vejaarrow-up-right mutable data

circle-exclamation

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.

circle-exclamation

const mutableTransformOrNull = Transform.getMutableOrNull(myEntity)

  • A e ou as funções Se 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, use e ou retorna um erro. retorna.

Null

Remover um component de uma entity Para remover um component de uma entity, use o deleteFrom()

Transform.deleteFrom(myEntity)

circle-exclamation

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

circle-info

💡 Dicaconst hasTransform = Transform.has(myEntity) : Você também podearrow-up-right 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.

circle-exclamation

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çarcomponent Transform : 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.RootEntity

  • Certos 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

circle-exclamation

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, comoarrow-up-right, skybox controlarrow-up-rightcursor position , ouarrow-up-right.

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, vejaarrow-up-rightuser data . O Transform do player é somente leitura; para modificá-lo use a função movePlayerTo() ,arrow-up-right.

saiba mais Você também pode anexar objetos ao player definindo-os como filhos dessa entity, embora oarrow-up-right 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 umaarrow-up-right.

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, vejaarrow-up-right.

Atualizado