Benutzerdefinierte Komponenten
Einführung
Benutzerdefinierte Komponenten können das visuelle Erscheinungsbild, die physikalischen Eigenschaften, die Eingabeverarbeitung oder die benutzerdefinierte Spiellogik definieren.Erstellen einer benutzerdefinierten Komponente
Um eine benutzerdefinierte Komponente zu erstellen, gehen Sie folgendermaßen vor:
- Klicken Sie im Dateibrowser auf die Plus-Schaltfläche (+).
- Klicken Sie auf "Neue Datei" → "Neue Komponentendatei" und geben Sie ihr einen Namen (Dateierweiterung optional).
- Es wird eine neue Komponentendatei, standardmäßig TypeScript, in Ihrem Projekt erzeugt.
- Die neue Komponentendatei enthält den für die Registrierung der benutzerdefinierten Komponente erforderlichen Boilerplate-Code.
Registrieren einer benutzerdefinierten Komponente
Der folgende Code ist ein Beispiel dafür, wie eine neu erstellte benutzerdefinierte Komponente im Code-Editor angezeigt wird:
Beispiel
Vermeiden Sie die Verwendung von "debug-" als Präfix für Komponentennamen. Komponentennamen, die mit 'debug-' beginnen, sind für interne Debugging-Zwecke reserviert und werden bei Verwendung in Ihrem Code nicht korrekt funktionieren.
// Dies ist eine Komponentendatei. Sie können diese Datei verwenden, um eine benutzerdefinierte Komponente für Ihr Projekt zu definieren.
// Diese Komponente wird als benutzerdefinierte Komponente im Editor angezeigt.
import * as ecs from '@8thwall/ecs' // So greifen Sie auf die ecs-Bibliothek zu.
ecs.registerComponent({
name: 'custom-component',
schema: {
// Fügen Sie Daten hinzu, die in der Komponente konfiguriert werden können.
},
schemaDefaults: {
// Fügen Sie Standardwerte für die Schemafelder hinzu.
},
data: {
// Hinzufügen von Daten, die nicht außerhalb der Komponente konfiguriert werden können.
},
add: (world, component) => {
// Wird ausgeführt, wenn die Komponente zur Welt hinzugefügt wird.
},
tick: (world, component) => {
// Läuft bei jedem Frame.
},
remove: (world, component) => {
// Läuft, wenn die Komponente aus der Welt entfernt wird.
},
})
Hinzufügen von benutzerdefinierten Komponenten zu einer Entität
Das folgende Beispiel zeigt, wie eine benutzerdefinierte Komponente zu einer vorhandenen Entität hinzugefügt werden kann.
Beispiel
Stellen Sie sicher, dass Sie die Komponente exportieren, bevor Sie versuchen, sie zu importieren oder irgendwo zu verwenden.
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' // Der Name der Datei ohne den Dateityp.
const demo = world.createEntity()
CustomComponent.set(world, demo, {
foo: 'bar'
})
Funktionen
Mit Komponentenfunktionen können Sie verschiedene Aktionen für eine Komponente und ihre Daten in Bezug auf eine Entität durchführen.
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)
Schema
Ein Schema ist eine Liste von Schlüssel-Werte-Paaren, die die Struktur einer Komponente definiert. Der Schlüssel ist der Name der Eigenschaft, und der Wert ist ein ECS-Typ, der die Art der Daten angibt, die diese Eigenschaft enthalten wird.
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 |
Beispiel
Das folgende Beispiel zeigt das Schema einer benutzerdefinierten Komponente.
schema: {
target: ecs.eid, // Eindeutige Entitätsreferenz für den NSC (Entity ID)
speed: ecs.f32, // Bewegungsgeschwindigkeit des NSC (32-bit float)
strength: ecs.f64, // Stärkestufe des NSC (64-bit float)
level: ecs.i32, // Charakterstufe des NPCs (32-bit integer)
armor: ecs.ui8, // Rüstungswert des NPCs (0-255, 8-bit unsigned integer)
experience: ecs.ui32, // Erfahrungspunkte des NPCs (32-bit unsigned integer)
guildName: ecs.string, // Name der Gilde zu der der NPC gehört. (String)
isHostile: ecs.boolean // Boolescher Wert, der angibt, ob der NPC dem Spieler feindlich gesinnt ist (Boolean)
}
schemaDefaults: {
speed: 3.14,
strength: 5.8,
level: 10,
armor: 255,
experience: 12,
guildName: 'Niantic Crew'
isHostile: false
}
Benutzerdefinierte Felder im Editor
Die Anzeige und Funktionalität Ihrer Komponenten im Entity-Editor kann auf verschiedene Weise angepasst werden. Dies geschieht über Kommentare innerhalb des Schemas, in denen die Felder mit // @
gekennzeichnet sind.
Etiketten
Manchmal müssen Bezeichnungen im Editor aussagekräftiger sein als ihre Namen im Code.
schema: {
// @label Foo
bar: ecs.eid,
},
Asset-Referenzen
Wenn Sie auf einen Vermögenswert und nicht auf eine Entität verweisen müssen.
schema: {
// @asset
yeti: ecs.eid,
}
Bedingungen
Eigenschaften können so eingestellt werden, dass sie nur in Abhängigkeit von den Werten anderer Eigenschaften angezeigt werden.
schema: {
// 'from' wird nur angezeigt, wenn autoFrom auf false gesetzt ist:
autoFrom: ecs.boolean,
// @condition autoFrom=false
from: ecs.f32,
// 'easingFunction' wird angezeigt, wenn entweder easeIn oder easeOut gesetzt ist:
easeIn: ecs.boolean,
easeOut: ecs.boolean,
// @condition easeIn=true|easeOut=true
easingFunction: ecs.string,
// 'targetX' wird nur angezeigt, wenn kein Ziel gesetzt ist:
target: ecs.eid,
// @condition target=null
targetX: ecs.f32,
}
Aufzählungen
Zeichenketteneigenschaften können auf eine bestimmte Liste beschränkt werden:
schema: {
// @enum Quadratic, Cubic, Quartic, Quintic, Sinusoidal, Exponential
easingFunction: ecs.string,
}
Gruppen
Bestimmte Gruppen von Eigenschaften können angewiesen werden, im Editor besonders behandelt zu werden. Gruppen werden wie folgt konfiguriert:
- Der Anfang und das Ende der Gruppe sind mit // @group start …gekennzeichnet. und // @Gruppe Ende
- Bedingungen können mit // @group condition auf die gesamte Gruppe angewendet werden
- Derzeit werden zwei Arten von Gruppen unterstützt: vector3 und color
Etiketten
Benutzerdefinierte Bezeichnungen können weiterhin für einzelne Felder verwendet werden:
schema: {
// @group start orient:vector3
// @label Pitch
orientPitch: ecs.f32,
// @label Yaw
orientYaw: ecs.f32,
// @label Roll
orientRoll: ecs.f32,
// @group end
}
Vektor3
Gruppen von Eigenschaften, die 3D-Vektoren darstellen, können wie folgt angegeben werden:
schema: {
autoFrom: ecs.boolean,
// @group start from:vector3
// @group condition autoFrom=false
fromX: ecs.f32,
fromY: ecs.f32,
fromZ: ecs.f32,
// @group end
}
Farbe
Die Farben können wie im folgenden Beispiel angegeben werden:
schema: {
// @group start background:color
bgRed: ecs.f32,
bgGreen: ecs.f32,
bgBlue: ecs.f32,
// @group end
}
Daten
Data ist ähnlich wie Schema, allerdings gibt es zwei bemerkenswerte Unterschiede.
- Daten können nicht außerhalb der Komponente, in der sie definiert sind, gelesen oder geschrieben werden.
- Für die Daten gibt es keine Standardwerte, sie können jedoch in der Lebenszyklusmethode "add" für eine ähnliche Funktionalität festgelegt werden.
Lebenszyklus-Methoden
Methode | Beschreibung |
---|---|
hinzufügen. | Wird einmal aufgerufen, wenn die Komponente initialisiert wird. Zum Einrichten des Anfangszustands und zum Instanziieren von Variablen |
entfernen | Wird aufgerufen, wenn die Komponente von der Entität entfernt wird oder wenn die Entität von der Szene abgetrennt wird. Wird verwendet, um alle vorherigen Änderungen an der Entität rückgängig zu machen. |
Zecke | Wird bei jeder Renderschleife oder jedem Tick der Szene aufgerufen. Wird für kontinuierliche Änderungen oder Kontrollen verwendet. |
Parameter
Eigenschaft | Typ | Beschreibung |
---|---|---|
Welt | Welt | Hinweis auf die Welt. |
Komponente | Komponentenobjekt | Verweis auf die aktuelle Komponente. |
KomponentenObjekt
Verwenden Sie schemaAttribute oder dataAttribute anstelle von eid-, schema- oder data-Eigenschaften in asynchronen Kontexten wie Timern oder Event-Handlern.
Eigenschaft | Typ | Beschreibung |
---|---|---|
eid | eid | Die Entitäts-ID der aktuellen Komponente |
Schema | Cursor | Verweis auf das Schema der aktuellen Entität |
schemaAttribute | KomponentenObjekt | Verweis auf das Schema der aktuellen Komponente im World Scope. |
Daten | Cursor | Verweis auf die Daten der aktuellen Entität |
dataAttribute | KomponentenObjekt | Verweis auf die Daten der aktuellen Komponente im World Scope. |