Entity Manipulation
Create or Destroy at runtime
Objects can be created and destroyed at runtime using the world
interface:
import {world} from '@8thwall/ecs'
const eid = world.createEntity()
world.deleteEntity(eid)
Create parent/child relationships
const parent = world.createEntity()
const child = world.createEntity()
world.setParent(child, parent)
world.getParent(child) // parent
world.getParent(parent) // 0 (no parent)
for (const eid of world.getChildren(parent)) {
console.log(eid, 'is a child of', parent)
}
Helper functions
There are a number of helper functions for interacting with entity transforms. We will be addin more over time as needed.
world.setScale(eid, 1, 1, 1)
world.setPosition(eid, 1, 1, 1)
world.setQuaternion(eid, 0, 0, 0, 1)
world.normalizeQuaternion(eid)
const tempMatrix = ecs.math.mat4.i()
world.getWorldTransform(eid1, tempMatrix)
world.setTransform(eid2, tempMatrix)
Entities are positioned relative to their parent. getWorldTransform
gets the world transform of
the object, taking parent transforms into account.
Register Behavior
A behavior is a function that runs on the world every tick.
ecs.registerBehavior(behavior)
const behavior = (world) => {
if (world.time.elapsed % 5000 - world.time.delta < 0) {
// 5 seconds have passed, spawn a new enemy
const eid = world.createEntity()
Enemy.set(world, eid, {health: 100})
}
}
ecs.registerBehavior(behavior)
Deactivate Behavior
Behaviors can also be deactivated with:
ecs.unregisterBehavior(behavior)
Query Behavior
Behaviors can run queries, which return lists of entity IDs.
const query = ecs.defineQuery([Enemy, Health]) // Query for Enemies that also have Health so we will know that Health.get() will not throw an error
const enemyDieBehavior = (world) => {
const enemies = query(world)
for (const enemyId in enemies) {
if (Health.get(world, enemyId).hp <= 0) {
world.destroyEntity(enemyId)
}
}
}
ecs.registerBehavior(enemyDieBehavior)
Depending on how many enemies there are, checking the health of every enemy on every tick might not be the most performant. The above is just an example.
Systems
Behaviors can also be implemented as "systems", which are a way to run a behavior on a query match, with efficient data lookup. To express the same logic from the previous example:
const enemyDieSystem = ecs.defineSystem(
[Enemy, Health],
(world, eid, [enemy, health]) => {
if (health.hp <= 0) {
world.destroyEntity(eid)
}
}
)
ecs.registerBehavior(enemyDieSystem)
The benefit of this approach is performance - the "enemy" and "health" cursors are pre-loaded, so iteration is very fast.