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

Components personalizados

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

Os dados sobre uma entity são armazenados no seu components. O Decentraland SDK 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 nestes, e alterará como a entity é rendered de acordo assim que eles mudarem seus valores.

Se a lógica da sua scene exigir armazenar informações sobre uma entity que não são tratadas pelos components padrão do SDK, então você pode criar um tipo customizado de component na sua scene. Você pode então build sistemas que verificam mudanças nesses components e respondem adequadamente.

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 este tipo de component. Isso pode ser qualquer string, desde que seja única.

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

  • default values (opcional): Um objeto contendo valores padrão para usar ao inicializar uma cópia do component, quando estes 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 deste component, que referenciam entities na scene. Quando você cria uma instância de um component, você fornece valores para cada um dos campos no schema do component. Os valores devem cumprir os tipos declarados de cada campo.

Se uma entity pai for escalada, todos os valores de position de suas filhas também serão escalados.
const wheel = 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 essa entity.

Seu custom component também pode realizar as outras funções comuns que estão 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ê atribui 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 onde ela está sendo usada, nem em outras libraries que também sejam usadas por esse projeto. Para evitar o risco de qualquer 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 inclui um MoveEntity component, defina o componentName desse component como MyUtilities::moveEntity.

Components como flags

Talvez você queira adicionar um component que simplesmente marque uma entity para diferenciá-la de outras, sem usá-lo para armazenar nenhum dado. Para fazer isso, deixe o schema como um objeto vazio.

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

Você pode então criar um system que itera sobre todas as entities com este component.

Component Schemas

Um schema descreve a estrutura dos dados dentro de um component. Um component pode armazenar quantos campos você quiser; cada um deve ser incluído na estrutura do schema. O schema pode incluir quantos níveis de itens aninhados forem necessários.

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 escolher criar o schema inline ao definir o component, ou, para mais legibilidade, 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 sugerirão 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 estes tipos de schema em um component assim para acompanhar o movimento gradual de uma entity. Este component armazena uma posição inicial e uma posição final como valores Vector3, além de uma velocidade e a fração do caminho 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 deste objeto como uma propriedade. Este objeto aninhado é essencialmente um schema em si, aninhado dentro do schema pai.

Alternativamente, para manter tudo mais legível e reutilizável, você pode alcançar o mesmo 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 seleção 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ê primeiro deve definir o enum. Depois, pode referenciá-lo usando Schemas.EnumNumber ou Schemas.EnumString, dependendo do tipo de enum. Você deve passar o enum para referência entre <>, assim como o tipo como parâmetro (seja Schemas.Int para enums numéricos, ou Schemas.String para enums de string). Você também deve passar um valor padrão para usar neste campo.

Tipos intercambiáveis

Você pode definir o tipo de um campo em um schema para seguir um padrão oneOf , no qual diferentes tipos 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 toda vez que você criar uma nova cópia.

O engine.defineComponent() recebe um terceiro argumento, que permite passar um objeto com valores para usar por padrão. Este objeto pode incluir alguns ou todos os valores do schema. Valores que não forem fornecidos nos defaults precisarão sempre ser fornecidos ao inicializar uma cópia do component.

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 deste component sem especificar nenhum valor, ele usará os definidos no padrão.

Subscribe to changes

Um caso de uso comum é executar uma function apenas quando os dados de um determinado component mudam. Use a OnChange function para evitar ter de definir um system e de comparar explicitamente valores antigos com novos valores.

Construindo systems para usar um component

Com seu component definido e adicionado às entities na sua scene, você pode criar Systems para executar 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 gira 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