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 :
- Dans le navigateur de fichiers, cliquez sur le bouton plus (+).
- Cliquez sur "Nouveau fichier" → "Nouveau fichier de composant", et donnez-lui un nom (extension de fichier facultative).
- Un nouveau fichier Component sera généré, TypeScript par défaut, dans votre projet.
- 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
É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
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.
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.
Type | Description |
---|---|
ecs.eid | Entity Reference |
ecs.f32 | 32-bit floating-point number |
ecs.f64 | 64-bit floating-point number |
ecs.i32 | 32-bit integer |
ecs.ui8 | 8-bit unsigned integer |
ecs.ui32 | 32-bit unsigned integer |
ecs.string | String |
ecs.boolean | Boolean |
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.
- Les données ne peuvent pas être lues ou écrites en dehors du composant dans lequel elles sont définies.
- 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éthode | Description |
---|---|
add | Appelé une fois lors de l'initialisation du composant. Utilisé pour mettre en place l'état initial et instancier les variables |
remove | Appelé 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é. |
tick | Appelé à chaque boucle de rendu ou à chaque tic de la scène. Utilisé pour les changements ou les contrôles continus. |
Paramètres
Propriété | Type | Description |
---|---|---|
world | World | Référence au monde. |
component | ComponentObject | Référence au composant actuel. |
ComponentObject
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é | Type | Description |
---|---|---|
eid | eid | L'ID de l'entité du composant actuel |
schema | Cursor | Référence au schéma de l'entité actuelle |
schemaAttribute | ComponentObject | Référence au schéma du composant actuel dans World Scope. |
data | Cursor | Référence aux données de l'entité actuelle |
dataAttribute | ComponentObject | Référence aux données de la composante actuelle dans World Scope. |