Skip to main content

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

for  number, {[Component]ComponentInstance}  in  World  do

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(
...ComponentInstance--

The component values to spawn the entity with.

) → number--

The new entity ID.

Spawns a new entity in the world with the given components.

spawnAt

World:spawnAt(
idnumber,--

The entity ID to spawn with

...ComponentInstance--

The component values to spawn the entity 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(
idnumber,--

The entity ID

...ComponentInstance--

The component values to spawn the entity with.

) → ()

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(
idnumber--

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(
idnumber--

The entity ID

) → bool--

true if the entity exists

Checks if the given entity ID is currently spawned in this world.

get

World:get(
entityIdnumber,--

The entity ID

...Component--

The components to fetch

) → ...--

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(
componentToTrackComponent,--

The component you want to listen to changes for.

...nil
) → () → (
id,
)--

Iterator of entity ID and change record

Types

interface ChangeRecord {
new?ComponentInstance--

The new value of the component. Nil if just removed.

old?ComponentInstance--

The former value of the component. Nil if just added.

}
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(
idnumber,--

The entity ID

...ComponentInstance--

The component values to insert

) → ()

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

World:remove(
idnumber,--

The entity ID

...Component--

The components to 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

deprecated in v0.9.0
</>
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.

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Creates a new World.",
            "params": [],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 105,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "__iter",
            "desc": "Iterates over all entities in this World. Iteration returns entity ID followed by a dictionary mapping\nComponent to Component Instance.\n\n**Usage:**\n\n```lua\nfor entityId, entityData in world do\n\tprint(entityId, entityData[Components.Example])\nend\n```",
            "params": [
                {
                    "name": "world",
                    "desc": "",
                    "lua_type": "World"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "number"
                },
                {
                    "desc": "",
                    "lua_type": "{[Component]: ComponentInstance}"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 154,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "startDeferring",
            "desc": "Starts deferring entity commands.\n\nIf you are using a [`Loop`](/api/Loop), this is done for you.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 410,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "commitCommands",
            "desc": "Sequentially processes all of the commands in the buffer.\n\nIf you are using a [`Loop`](/api/Loop), this is called after every system.\nHowever, you can call it more often if you want.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 420,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "stopDeferring",
            "desc": "Stops deferring entity commands and processes all commands left in the buffer.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 431,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "spawn",
            "desc": "Spawns a new entity in the world with the given components.",
            "params": [
                {
                    "name": "...",
                    "desc": "The component values to spawn the entity with.",
                    "lua_type": "ComponentInstance"
                }
            ],
            "returns": [
                {
                    "desc": "The new entity ID.",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 442,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "spawnAt",
            "desc": "Spawns a new entity in the world with a specific entity ID and given components.\n\nThe next ID generated from [World:spawn] will be increased as needed to never collide with a manually specified ID.",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID to spawn with",
                    "lua_type": "number"
                },
                {
                    "name": "...",
                    "desc": "The component values to spawn the entity with.",
                    "lua_type": "ComponentInstance"
                }
            ],
            "returns": [
                {
                    "desc": "The same entity ID that was passed in",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 456,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "replace",
            "desc": "Replaces a given entity by ID with an entirely new set of components.\nEquivalent to removing all components from an entity, and then adding these ones.",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID",
                    "lua_type": "number"
                },
                {
                    "name": "...",
                    "desc": "The component values to spawn the entity with.",
                    "lua_type": "ComponentInstance"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 487,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "despawn",
            "desc": "Despawns a given entity by ID, removing it and all its components from the world entirely.",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID",
                    "lua_type": "number"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 499,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "clear",
            "desc": "Removes all entities from the world.\n\n:::caution\nRemoving entities in this way is not reported by `queryChanged`.\n:::",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 514,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "contains",
            "desc": "Checks if the given entity ID is currently spawned in this world.",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if the entity exists",
                    "lua_type": "bool"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 531,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "get",
            "desc": "Gets a specific component (or set of components) from a specific entity in this world.",
            "params": [
                {
                    "name": "entityId",
                    "desc": "The entity ID",
                    "lua_type": "number"
                },
                {
                    "name": "...",
                    "desc": "The components to fetch",
                    "lua_type": "Component"
                }
            ],
            "returns": [
                {
                    "desc": "Returns the component values in the same order they were passed in",
                    "lua_type": "..."
                }
            ],
            "function_type": "method",
            "source": {
                "line": 552,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "query",
            "desc": "Performs a query against the entities in this World. Returns a [QueryResult](/api/QueryResult), which iterates over\nthe results of the query.\n\nOrder of iteration is not guaranteed.\n\n```lua\nfor id, enemy, charge, model in world:query(Enemy, Charge, Model) do\n\t-- Do something\nend\n\nfor id in world:query(Target):without(Model) do\n\t-- Again, with feeling\nend\n```",
            "params": [
                {
                    "name": "...",
                    "desc": "The component types to query. Only entities with *all* of these components will be returned.",
                    "lua_type": "Component"
                }
            ],
            "returns": [
                {
                    "desc": "See [QueryResult](/api/QueryResult) docs.",
                    "lua_type": "QueryResult"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 1043,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "queryChanged",
            "desc": ":::info Topologically-aware function\nThis function is only usable if called within the context of [`Loop:begin`](/api/Loop#begin).\n:::\n\nQueries for components that have changed **since the last time your system ran `queryChanged`**.\n\nOnly one changed record is returned per entity, even if the same entity changed multiple times. The order\nin which changed records are returned is not guaranteed to be the order that the changes occurred in.\n\nIt should be noted that `queryChanged` does not have the same iterator invalidation concerns as `World:query`.\n\n:::tip\nThe first time your system runs (i.e., on the first frame), all existing entities in the world that match your query\nare returned as \"new\" change records.\n:::\n\n:::info\nCalling this function from your system creates storage internally for your system. Then, changes meeting your\ncriteria are pushed into your storage. Calling `queryChanged` again each frame drains this storage.\n\nIf your system isn't called every frame, the storage will continually fill up and does not empty unless you drain\nit.\n\nIf you stop calling `queryChanged` in your system, changes will stop being tracked.\n:::\n\n### Returns\n`queryChanged` returns an iterator function, so you call it in a for loop just like `World:query`.\n\nThe iterator returns the entity ID, followed by a [`ChangeRecord`](#ChangeRecord).\n\nThe `ChangeRecord` type is a table that contains two fields, `new` and `old`, respectively containing the new\ncomponent instance, and the old component instance. `new` and `old` will never be the same value.\n\n`new` will be nil if the component was removed (or the entity was despawned), and `old` will be nil if the\ncomponent was just added.\n\nThe `old` field will be the value of the component the last time this system observed it, not\nnecessarily the value it changed from most recently.\n\nThe `ChangeRecord` table is potentially shared with multiple systems tracking changes for this component, so it\ncannot be modified.\n\n```lua\nfor id, record in world:queryChanged(Model) do\n\tif record.new == nil then\n\t\t-- Model was removed\n\n\t\tif enemy.type == \"this is a made up example\" then\n\t\t\tworld:remove(id, Enemy)\n\t\tend\n\tend\nend\n```",
            "params": [
                {
                    "name": "componentToTrack",
                    "desc": "The component you want to listen to changes for.",
                    "lua_type": "Component"
                },
                {
                    "name": "...",
                    "desc": "",
                    "lua_type": "nil"
                }
            ],
            "returns": [
                {
                    "desc": "Iterator of entity ID and change record",
                    "lua_type": "() -> (id, ChangeRecord)"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 1193,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "insert",
            "desc": "Inserts a component (or set of components) into an existing entity.\n\nIf another instance of a given component already exists on this entity, it is replaced.\n\n```lua\nworld:insert(\n\tentityId,\n\tComponentA({\n\t\tfoo = \"bar\"\n\t}),\n\tComponentB({\n\t\tbaz = \"qux\"\n\t})\n)\n```",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID",
                    "lua_type": "number"
                },
                {
                    "name": "...",
                    "desc": "The component values to insert",
                    "lua_type": "ComponentInstance"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 1282,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "remove",
            "desc": "Removes a component (or set of components) from an existing entity.\n\n```lua\nlocal removedA, removedB = world:remove(entityId, ComponentA, ComponentB)\n```",
            "params": [
                {
                    "name": "id",
                    "desc": "The entity ID",
                    "lua_type": "number"
                },
                {
                    "name": "...",
                    "desc": "The components to remove",
                    "lua_type": "Component"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 1301,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "size",
            "desc": "Returns the number of entities currently spawned in the world.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 1323,
                "path": "lib/World.luau"
            }
        },
        {
            "name": "optimizeQueries",
            "desc": ":::tip\n[Loop] automatically calls this function on your World(s), so there is no need to call it yourself if you're using\na Loop.\n:::\n\nIf you are not using a Loop, you should call this function at a regular interval (i.e., once per frame) to optimize\nthe internal storage for queries.\n\nThis is part of a strategy to eliminate iterator invalidation when modifying the World while inside a query from\n[World:query]. While inside a query, any changes to the World are stored in a separate location from the rest of\nthe World. Calling this function combines the separate storage back into the main storage, which speeds things up\nagain.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "deprecated": {
                "version": "v0.9.0",
                "desc": "With the introduction of command buffering only one storage will ever exist at a time."
            },
            "source": {
                "line": 1343,
                "path": "lib/World.luau"
            }
        }
    ],
    "properties": [],
    "types": [
        {
            "name": "ChangeRecord",
            "desc": "",
            "fields": [
                {
                    "name": "new?",
                    "lua_type": "ComponentInstance",
                    "desc": "The new value of the component. Nil if just removed."
                },
                {
                    "name": "old?",
                    "lua_type": "ComponentInstance",
                    "desc": "The former value of the component. Nil if just added."
                }
            ],
            "source": {
                "line": 1133,
                "path": "lib/World.luau"
            }
        }
    ],
    "name": "World",
    "desc": "A World contains entities which have components.\nThe World is queryable and can be used to get entities with a specific set of components.\nEntities are simply ever-increasing integers.",
    "source": {
        "line": 74,
        "path": "lib/World.luau"
    }
}