Zum Hauptinhalt springen

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:

  1. Klicken Sie im Dateibrowser auf die Plus-Schaltfläche (+).
  2. Klicken Sie auf "Neue Datei" → "Neue Komponentendatei" und geben Sie ihr einen Namen (Dateierweiterung optional).
    1. Es wird eine neue Komponentendatei, standardmäßig TypeScript, in Ihrem Projekt erzeugt.
    2. 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

gefahr

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

tipp

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.

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

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.

  1. Daten können nicht außerhalb der Komponente, in der sie definiert sind, gelesen oder geschrieben werden.
  2. 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

MethodeBeschreibung
hinzufügen.Wird einmal aufgerufen, wenn die Komponente initialisiert wird. Zum Einrichten des Anfangszustands und zum Instanziieren von Variablen
entfernenWird 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.
ZeckeWird bei jeder Renderschleife oder jedem Tick der Szene aufgerufen. Wird für kontinuierliche Änderungen oder Kontrollen verwendet.

Parameter

EigenschaftTypBeschreibung
WeltWeltHinweis auf die Welt.
KomponenteKomponentenobjektVerweis auf die aktuelle Komponente.

KomponentenObjekt

Warnung

Verwenden Sie schemaAttribute oder dataAttribute anstelle von eid-, schema- oder data-Eigenschaften in asynchronen Kontexten wie Timern oder Event-Handlern.

EigenschaftTypBeschreibung
eideidDie Entitäts-ID der aktuellen Komponente
SchemaCursorVerweis auf das Schema der aktuellen Entität
schemaAttributeKomponentenObjektVerweis auf das Schema der aktuellen Komponente im World Scope.
DatenCursorVerweis auf die Daten der aktuellen Entität
dataAttributeKomponentenObjektVerweis auf die Daten der aktuellen Komponente im World Scope.