World
A World contains entities which have components. The World is queryable and can be used to get entities with a specific set of components. Entities are simply ever-increasing integers.
Functions
new
World.
new
(
) →
(
)
Creates a new World.
iterating over World
Iterates over all entities in this World. Iteration returns entity ID followed by a dictionary mapping Component to Component Instance.
Usage:
for entityId, entityData in world do
print(entityId, entityData[Components.Example])
end
startDeferring
World:
startDeferring
(
) →
(
)
Starts deferring entity commands.
If you are using a Loop
, this is done for you.
commitCommands
World:
commitCommands
(
) →
(
)
Sequentially processes all of the commands in the buffer.
If you are using a Loop
, this is called after every system.
However, you can call it more often if you want.
stopDeferring
World:
stopDeferring
(
) →
(
)
Stops deferring entity commands and processes all commands left in the buffer.
spawn
World:
spawn
(
) →
number
--
The new entity ID.
Spawns a new entity in the world with the given components.
spawnAt
World:
spawnAt
(
id:
number
,
--
The entity ID to spawn with
) →
number
--
The same entity ID that was passed in
Spawns a new entity in the world with a specific entity ID and given components.
The next ID generated from World:spawn will be increased as needed to never collide with a manually specified ID.
replace
World:
replace
(
id:
number
,
--
The entity ID
) →
(
)
Replaces a given entity by ID with an entirely new set of components. Equivalent to removing all components from an entity, and then adding these ones.
despawn
World:
despawn
(
id:
number
--
The entity ID
) →
(
)
Despawns a given entity by ID, removing it and all its components from the world entirely.
clear
World:
clear
(
) →
(
)
Removes all entities from the world.
caution
Removing entities in this way is not reported by queryChanged
.
contains
World:
contains
(
id:
number
--
The entity ID
) →
bool
--
true
if the entity exists
Checks if the given entity ID is currently spawned in this world.
get
World:
get
(
entityId:
number
,
--
The entity ID
) →
...
--
Returns the component values in the same order they were passed in
Gets a specific component (or set of components) from a specific entity in this world.
query
World:
query
(
...:
Component
--
The component types to query. Only entities with all of these components will be returned.
) →
QueryResult
--
See QueryResult docs.
Performs a query against the entities in this World. Returns a QueryResult, which iterates over the results of the query.
Order of iteration is not guaranteed.
for id, enemy, charge, model in world:query(Enemy, Charge, Model) do
-- Do something
end
for id in world:query(Target):without(Model) do
-- Again, with feeling
end
queryChanged
World:
queryChanged
(
...:
nil
) →
(
)
→
(
id
,
)
--
Iterator of entity ID and change record
Types
interface
ChangeRecord {
}
Topologically-aware function
This function is only usable if called within the context of Loop:begin
.
Queries for components that have changed since the last time your system ran queryChanged
.
Only one changed record is returned per entity, even if the same entity changed multiple times. The order in which changed records are returned is not guaranteed to be the order that the changes occurred in.
It should be noted that queryChanged
does not have the same iterator invalidation concerns as World:query
.
tip
The first time your system runs (i.e., on the first frame), all existing entities in the world that match your query are returned as "new" change records.
info
Calling this function from your system creates storage internally for your system. Then, changes meeting your
criteria are pushed into your storage. Calling queryChanged
again each frame drains this storage.
If your system isn't called every frame, the storage will continually fill up and does not empty unless you drain it.
If you stop calling queryChanged
in your system, changes will stop being tracked.
Returns
queryChanged
returns an iterator function, so you call it in a for loop just like World:query
.
The iterator returns the entity ID, followed by a ChangeRecord
.
The ChangeRecord
type is a table that contains two fields, new
and old
, respectively containing the new
component instance, and the old component instance. new
and old
will never be the same value.
new
will be nil if the component was removed (or the entity was despawned), and old
will be nil if the
component was just added.
The old
field will be the value of the component the last time this system observed it, not
necessarily the value it changed from most recently.
The ChangeRecord
table is potentially shared with multiple systems tracking changes for this component, so it
cannot be modified.
for id, record in world:queryChanged(Model) do
if record.new == nil then
-- Model was removed
if enemy.type == "this is a made up example" then
world:remove(id, Enemy)
end
end
end
insert
World:
insert
(
id:
number
,
--
The entity ID
) →
(
)
Inserts a component (or set of components) into an existing entity.
If another instance of a given component already exists on this entity, it is replaced.
world:insert(
entityId,
ComponentA({
foo = "bar"
}),
ComponentB({
baz = "qux"
})
)
remove
Removes a component (or set of components) from an existing entity.
local removedA, removedB = world:remove(entityId, ComponentA, ComponentB)
size
World:
size
(
) →
(
)
Returns the number of entities currently spawned in the world.
optimizeQueries
This was deprecated in v0.9.0
With the introduction of command buffering only one storage will ever exist at a time.
World:
optimizeQueries
(
) →
(
)
tip
Loop automatically calls this function on your World(s), so there is no need to call it yourself if you're using a Loop.
If you are not using a Loop, you should call this function at a regular interval (i.e., once per frame) to optimize the internal storage for queries.
This is part of a strategy to eliminate iterator invalidation when modifying the World while inside a query from World:query. While inside a query, any changes to the World are stored in a separate location from the rest of the World. Calling this function combines the separate storage back into the main storage, which speeds things up again.