Passer au contenu principal

Composants personnalisés

Introduction

Les composants personnalisés peuvent définir l'apparence visuelle, les propriétés physiques, la gestion des entrées ou la logique de jeu personnalisée.

Création d'un composant personnalisé

Pour créer un composant personnalisé, procédez comme suit :

  1. Dans le navigateur de fichiers, cliquez sur le bouton plus (+).
  2. Cliquez sur "Nouveau fichier" → "Nouveau fichier de composant", et donnez-lui un nom (extension de fichier facultative).
    1. Un nouveau fichier Component sera généré, TypeScript par défaut, dans votre projet.
    2. Le nouveau fichier de composant comprendra le code de base nécessaire à l'enregistrement du composant personnalisé.

Enregistrement d'un composant personnalisé

Le code suivant est un exemple de la façon dont un composant personnalisé nouvellement créé apparaîtra dans l'éditeur de code :

Exemple

danger

Évitez d'utiliser "debug-" comme préfixe pour les noms de composants. Les noms de composants commençant par "debug-" sont réservés à des fins de débogage interne et ne fonctionneront pas correctement s'ils sont utilisés dans votre code.

// Il s'agit d'un fichier de composant. Vous pouvez utiliser ce fichier pour définir un composant personnalisé pour votre projet.
// Ce composant apparaîtra comme un composant personnalisé dans l'éditeur.

import * as ecs from '@8thwall/ecs' // C'est ainsi que vous accédez à la bibliothèque ecs.

ecs.registerComponent({
name : 'custom-component',
schema : {
// Ajoutez des données qui peuvent être configurées sur le composant.
},
schemaDefaults : {
// Ajoute des valeurs par défaut pour les champs du schéma.
},
data : {
// Ajoute des données qui ne peuvent pas être configurées en dehors du composant.
},
add : (world, component) => {
// S'exécute lorsque le composant est ajouté au monde.
},
tick : (world, component) => {
// S'exécute à chaque image.
},
remove : (world, component) => {
// S'exécute lorsque le composant est retiré du monde.
},
})

Ajout de composants personnalisés à une entité

L'exemple suivant montre comment ajouter un composant personnalisé à une entité existante.

Exemple

conseil

Veillez à exporter le composant avant d'essayer de l'importer ou de l'utiliser où que ce soit.

import * as ecs from '@8thwall/ecs'

const CustomComponent = ecs.registerComponent({
name : 'custom-component',
schema : {
foo: ecs.string
},
schemaDefaults : {
},
data : {
},
add : (world, component) => {
},
tick : (world, component) => {
},
remove : (world, component) => {
},
})

export {CustomComponent}
import CustomComponent from './custom-component' // Le nom du fichier sans le type de fichier.

const demo = world.createEntity()

CustomComponent.set(world, demo, {
foo: 'bar'
})

Fonctions

Les fonctions des composants permettent d'effectuer différentes actions sur un composant et ses données en relation avec une entité.

Get

Returns a read-only reference.

Example

ecs.CylinderGeometry.get(world, component.eid)

Set

Ensures the component exists on the entity, then assigns the (optional) data to the component.

Example

ecs.CylinderGeometry.set(world, component.eid, {
radius: 1,
height: 1
})

Mutate

Perform an update to the component within a callback function. Return true to indicate no changes made.

Example

ecs.CylinderGeometry.mutate(world, component.eid, (cursor) => {
cursor.radius += 1 ;
cursor.height *= 2 ;
return false;
})

Remove

Removes the component from the entity.

Example

ecs.CylinderGeometry.remove(world, component.eid)

Has

Returns true if the component is present on the entity.

Example

ecs.CylinderGeometry.has(world, component.eid)

Reset

Adds, or resets the component to its default state.

Example

ecs.CylinderGeometry.reset(world, component.eid)

Advanced Functions

Cursor

Returns a mutable reference. Cursors are reused so only one cursor for each component can exist at a time.

Example
ecs.CylinderGeometry.cursor(world, component.eid)

Acquire

Same behavior as cursor, but commit must be called after the cursor is done being used.

Example
ecs.CylinderGeometry.acquire(world, component.eid)

Commit

Called after acquire. An optional third argument determines whether the cursor was mutated or not.

Example
ecs.CylinderGeometry.commit(world, component.eid)
ecs.CylinderGeometry.commit(world, component.eid, false)

Dirty

Mark the entity as having been mutated. Only needed in a specific case where systems are mutating data.

Example
ecs.CylinderGeometry.dirty(world, component.eid)

Schéma

Un schéma est une liste de paires clé-valeur qui définit la structure d'un composant. La clé est le nom de la propriété et la valeur est un type ECS qui spécifie le type de données que la propriété contiendra.

info

Currently, storing dynamically sized objects or lists isn’t supported. We’re actively exploring this feature and would love to hear about your specific use cases.

The following data types are useful for creating Schema properties on a Custom Component or references to a specific type.

TypeDescription
ecs.eidEntity Reference
ecs.f3232-bit floating-point number
ecs.f6464-bit floating-point number
ecs.i3232-bit integer
ecs.ui88-bit unsigned integer
ecs.ui3232-bit unsigned integer
ecs.stringString
ecs.booleanBoolean

Exemple

L'exemple suivant montre le schéma d'un composant personnalisé.

schema : {
target : ecs.eid, // Référence unique de l'entité pour le PNJ (Entity ID)
speed : ecs.f32, // Vitesse de déplacement du PNJ (32-bit float)
strength : ecs.f64, // Niveau de force du PNJ (64-bit float)
level : ecs.i32, // Niveau de personnage du PNJ (entier 32 bits)
armor : ecs.ui8, // Indice d'armure du PNJ (0-255, entier 8 bits non signé)
experience : ecs.ui32, // Points d'expérience du PNJ (entier 32 bits non signé)
guildName : ecs.string, // Nom de la guilde à laquelle appartient le PNJ (chaîne de caractères). (Chaîne)
isHostile : ecs.boolean // Booléen indiquant si le PNJ est hostile au joueur (Booléen)
}
schemaDefaults : {
vitesse : 3.14,
force : 5.8,
niveau : 10,
armure : 255,
expérience : 12,
guildName : 'Niantic Crew'
isHostile : false
}

Champs personnalisés de l'éditeur

L'affichage et la fonctionnalité de vos composants dans l'éditeur d'entités peuvent être personnalisés de différentes manières. Tout cela se fait à l'aide de commentaires dans le schéma où les champs sont marqués // @.

Étiquettes

Parfois, les étiquettes dans l'éditeur doivent être plus descriptives que leurs noms dans le code.

schema : {
// @label Foo
bar : ecs.eid,
},

Références des actifs

Si vous devez référencer un actif plutôt qu'une entité.

schema : {
// @asset
yeti : ecs.eid,
}

Conditions

Les propriétés peuvent être paramétrées pour ne s'afficher qu'en fonction des valeurs d'autres propriétés.

schema : {
// 'from' ne s'affichera que si autoFrom est réglé sur false :
autoFrom : ecs.boolean,
// @condition autoFrom=false
from : ecs.f32,

// 'easingFunction' s'affichera si easeIn ou easeOut sont réglés :
easeIn : ecs.boolean,
easeOut : ecs.boolean,
// @condition easeIn=true|easeOut=true
easingFunction : ecs.string,

// 'targetX' ne s'affiche que si aucune cible n'est définie :
target : ecs.eid,
// @condition target=null
targetX : ecs.f32,
}

Les énumérations

Les propriétés des chaînes de caractères peuvent être limitées à une liste définie :

schema : {
// @enum Quadratique, Cubique, Quartique, Quintique, Sinusoïdale, Exponentielle
easingFunction : ecs.string,
}

Groupes

Il est possible de demander à certains groupes de biens de faire l'objet d'un traitement particulier dans l'éditeur. Les groupes sont configurés comme suit :

  • Le début et la fin du groupe sont marqués par // @group start … et // @group end
  • Les conditions peuvent être appliquées à l'ensemble du groupe avec // @group condition
  • Deux types de groupes sont actuellement pris en charge : vector3 et color
Étiquettes

Les étiquettes personnalisées peuvent toujours être utilisées pour des champs individuels :

schema : {
// @group start orient:vector3
// @label Pitch
orientPitch : ecs.f32,
// @label Yaw
orientYaw : ecs.f32,
// @label Roll
orientRoll : ecs.f32,
// @group end
}
Vecteur3

Les groupes de propriétés qui représentent des vecteurs 3D peuvent être indiqués comme suit :

schema : {
autoFrom : ecs.boolean,
// @group start from:vector3
// @group condition autoFrom=false
fromX : ecs.f32,
fromY : ecs.f32,
fromZ : ecs.f32,
// @group end
}
Couleur

Les couleurs peuvent être indiquées comme dans l'exemple suivant :

schema : {
// @group start background:color
bgRed : ecs.f32,
bgGreen : ecs.f32,
bgBlue : ecs.f32,
// @group end
}

Données

Data est similaire à Schema, mais il y a deux différences notables.

  1. Les données ne peuvent pas être lues ou écrites en dehors du composant dans lequel elles sont définies.
  2. Les données n'ont pas de valeurs par défaut, mais elles peuvent être définies dans la méthode de cycle de vie "add" pour une fonctionnalité similaire.

Méthodes de cycle de vie

MéthodeDescription
addAppelé une fois lors de l'initialisation du composant. Utilisé pour mettre en place l'état initial et instancier les variables
removeAppelé lorsque le composant est retiré de l'entité ou lorsque l'entité est détachée de la scène. Permet d'annuler toutes les modifications précédentes apportées à l'entité.
tickAppelé à chaque boucle de rendu ou à chaque tic de la scène. Utilisé pour les changements ou les contrôles continus.

Paramètres

PropriétéTypeDescription
worldWorldRéférence au monde.
componentComponentObjectRéférence au composant actuel.

ComponentObject

avertissement

Utilisez schemaAttribute ou dataAttribute au lieu des propriétés eid, schema ou data dans des contextes asynchrones tels que les temporisateurs ou les gestionnaires d'événements.

PropriétéTypeDescription
eideidL'ID de l'entité du composant actuel
schemaCursorRéférence au schéma de l'entité actuelle
schemaAttributeComponentObjectRéférence au schéma du composant actuel dans World Scope.
dataCursorRéférence aux données de l'entité actuelle
dataAttributeComponentObjectRéférence aux données de la composante actuelle dans World Scope.