For the complete documentation index, see llms.txt. This page is also available as Markdown.

Custom Components

Crie um custom component para lidar com dados específicos relacionados a uma entity

Os dados sobre uma entity são armazenados em seu components. O SDK da Decentraland fornece uma série de base components que gerenciam diferentes aspectos de uma entity, como sua posição, shape, material, etc. O engine sabe como interpretar as informações nesses componentes e vai alterar como a entity é renderizada de acordo assim que os valores deles mudarem.

Se a lógica da sua scene exigir armazenar informações sobre uma entity que não sejam tratadas pelos default components do SDK, então você pode criar um tipo customizado de component na sua scene. Depois, você pode construir systems que verifiquem mudanças nesses components e reajam de acordo.

Sobre definir components

Para definir um novo component, use engine.defineComponent. Cada component precisa do seguinte:

  • Um componentName: Um identificador de string único que o SDK usa internamente para identificar esse tipo de component. Pode ser qualquer string, desde que seja única.

  • Um schema: Uma class que define a estrutura de dados mantida pelo component.

  • default values (opcional): Um objeto contendo valores padrão a serem usados para inicializar uma cópia do component, quando eles não forem fornecidos.

export const WheelSpinComponent = engine.defineComponent('wheelSpinComponent', {
	spinning: Schemas.Boolean,
	speed: Schemas.Float,
})

Depois de definir um custom component, você pode criar instâncias desse component, que fazem referência a entities na scene. Quando você cria uma instância de um component, você fornece valores para cada um dos campos do schema do component. Os valores devem estar em conformidade com os tipos declarados de cada campo.

// Criar entities
const wheel1 = engine.addEntity()
const wheel2 = engine.addEntity()

// Criar instâncias do component
WheelSpinComponent.create(wheel1, {
	spinning: true,
	speed: 10,
})

WheelSpinComponent.create(wheel2, {
	spinning: false,
	speed: 0,
})

Cada entity que tem o component adicionado instancia uma nova cópia do component, contendo dados específicos para aquela entity.

Seu custom component também pode executar as outras funções comuns disponíveis em outros components:

Sobre o componentName

Cada component deve ter um nome ou identificador de component único, que o diferencie internamente. Você não precisará usar esse identificador interno em nenhum outro lugar do seu código. Uma boa prática é usar o mesmo nome que você atribuir ao component, mas começando com uma letra minúscula; o que realmente importa é que esse identificador seja único dentro do projeto.

Ao criar components que serão compartilhados como parte de uma library, tenha em mente que os nomes dos components na sua library não devem se sobrepor a nenhum nome de component no projeto em que ela estiver sendo usada, nem em outras libraries que também sejam usadas por esse projeto. Para evitar o risco de sobreposição, a melhor prática recomendada é incluir o nome da library como parte da componentName string. Você pode seguir esta fórmula: ${packageName}::${componentName}. Por exemplo, se você criar umaMyUtilities library que inclua um MoveEntity component, defina o componentName desse component como MyUtilities::moveEntity.

Components como flags

Você pode querer adicionar um component que apenas marque uma entity para diferenciá-la das outras, sem usá-lo para armazenar qualquer dado. Para fazer isso, deixe o schema como um objeto vazio.

Isso é especialmente útil ao usar querying components. Um simple flag component pode ser usado para distinguir entities das outras e evitar que o system itere sobre mais entities do que o necessário.

Depois, você pode criar um system que itere sobre todas as entities com esse component.

Schemas de Component

Um schema descreve a estrutura dos dados dentro de um component. Um component pode armazenar quantos campos você quiser, e cada um deles deve ser incluído na estrutura do schema. O schema pode incluir quantos níveis de itens aninhados você precisar.

Cada campo no schema deve incluir uma declaração de tipo. Você só pode usar os tipos especiais de schema fornecidos pelo SDK. Por exemplo, use o tipo Schemas.Boolean em vez do tipo boolean. Escreva Schemas. e seu IDE exibirá todas as opções disponíveis.

O exemplo acima define um component cujo schema contém dois valores, um spinning boolean e um speed número de ponto flutuante.

Você pode optar por criar o schema inline ao definir o component, ou, para mais legibilidade, você pode criá-lo e então referenciá-lo.

💡 Dica: Ao criar uma instância de um component, as opções de autocomplete do VS Studio vão sugerir quais campos você pode adicionar ao component ao pressionar Ctrl + Space.

Tipos de Schema padrão

Os seguintes tipos básicos estão disponíveis para uso dentro dos campos de um schema:

  • Schemas.Boolean

  • Schemas.Byte

  • Schemas.Double

  • Schemas.Float

  • Schemas.Int

  • Schemas.Int64

  • Schemas.Number

  • Schemas.Short

  • Schemas.String

  • Schemas.Entity

Os seguintes tipos complexos também existem. Cada um inclui uma série de propriedades aninhadas com valores numéricos.

  • Schemas.Vector3

  • Schemas.Quaternion

  • Schemas.Color3

  • Schemas.Color4

💡 Dica: Consulte Tipos de geometria e Tipos de cor para mais detalhes sobre como esses tipos de dados são úteis.

Por exemplo, você pode usar esses tipos de schema em um component assim para acompanhar o movimento gradual de uma entity. Esse component armazena uma posição inicial e uma final como valores Vector3, além de uma velocidade e da fração do percurso concluído como números float. Veja Mover entities para a implementação completa deste exemplo.

Tipos de array

Para definir o tipo de um campo como um array, use Schemas.Array(). Passe o tipo dos elementos no array como uma propriedade.

Tipos de schema aninhados

Para definir o tipo de um campo como um objeto, use Schemas.Map(). Passe o conteúdo desse objeto como uma propriedade. Esse objeto aninhado é essencialmente um schema em si, aninhado dentro do schema pai.

Como alternativa, para manter as coisas mais legíveis e reutilizáveis, você pode obter o mesmo resultado definindo o schema aninhado separadamente e depois referenciando-o ao definir o schema pai.

Tipos de Enums

Você pode definir o tipo de um campo em um schema como um enum. Enums facilitam a escolha entre um número finito de opções, fornecendo valores legíveis por humanos para cada uma.

Para definir o tipo de um campo como um enum, você precisa primeiro definir o enum. Depois, você pode referenciá-lo usando Schemas.EnumNumber ou Schemas.EnumString, dependendo do tipo de enum. Essas funções recebem dois parâmetros: o enum a ser referenciado e um valor padrão a ser usado para esse campo.

Tipos intercambiáveis

Você pode definir o tipo de um campo em um schema para seguir um padrão oneOf , em que tipos diferentes podem ser aceitos.

Ao criar uma instância do component, você precisa especificar o tipo selecionado com um $case, por exemplo:

Valores padrão

Muitas vezes é bom ter valores padrão em seus components, para que não seja necessário definir explicitamente cada valor sempre que você criar uma nova cópia.

O engine.defineComponent() função recebe um terceiro argumento, que permite passar um objeto com valores a serem usados por padrão. Esse objeto pode incluir todos ou alguns dos valores do schema. Os campos não cobertos pelos padrões ou pelos valores que você fornecer ao inicializar uma cópia do component são inicializados com um valor semelhante a zero, como 0, false, ou uma string vazia, dependendo do tipo.

O exemplo acima cria um WheelSpinComponent component que inclui tanto um schema quanto um conjunto de valores padrão a serem usados. Se você então inicializar uma cópia desse component sem especificar nenhum valor, ele usará os definidos no padrão.

Subscrever alterações

Um caso de uso comum é executar uma função apenas se os dados de um certo component mudarem. Use a OnChange function para evitar ter que definir um system e ter que comparar explicitamente valores antigos com novos valores.

Criando systems para usar um component

Com o seu component definido e adicionado a entities na sua scene, você pode criar Systems para executar a lógica, fazendo uso desses dados armazenados no component.

O exemplo acima define um system que itera sobre todas as entities que incluem o custom wheelSpinComponent, e as rotaciona levemente a cada tick do game loop. A quantidade dessa rotação é proporcional ao speed valor armazenado na instância do component de cada entity. O exemplo faz uso de component queries para obter apenas as entities relevantes.

Atualizado