Commands are similar to remote procedure calls (RPCs). There are two main types of commands: component commands and world commands.
Component commands are commands that are invoked on a component inside an entity by a worker, and are responded to by whichever worker has write access to the component. These commands can perform any action, since you define their behaviour. By default, commands are routed through SpatialOS, which provides some guarantees. However, you can specify that the command should be handled locally when the worker sending the command also has write access to the target component - we refer to locally-handled commands as “short circuiting”. This avoids the round trip to SpatialOS in some cases, but comes with its own pitfalls, which are detailed below.
You define commands in your schema, as part of a component. They can be used for communication and requests between different entities.
For details on how to implement commands, see the SDK-specific docs:
World commands are built-in SpatialOS commands, invoked on the SpatialOS world. They allow you to directly manipulate your simulated world by creating entities, deleting entities and querying the world for entities.
In order to send a world command, a worker must have permission to do so. For more information, see the Worker permissions page.
Creating and deleting entities
To create an entity, you set up a template specifying the components contained within that entity,
and the initial values of their properties, then send a
To delete an entity, you need to know its
EntityId. One way of finding this out is using an
entity query (see below).
For details on how to create and delete entities, see the SDK-specific docs:
Querying the world
You can run entity queries in order to get information about entities in the world. To do this, you build a query, and then use a world command to execute it.
Entity queries can search for the entities with the following attributes:
- a specific
- a specific component
- within a specific sphere in the world
and any combination of the above, using
Based on the set of entities that match it, a query can return:
- snapshots of those entities, including all components
- snapshots of those entities, including only the components you specify
- the number of entities
Important: You should keep entity queries as limited as possible. All queries hit the network and cause a runtime lookup, which is expensive even in the best cases. This means you should:
- always limit queries to a specific sphere of the world
- only return the information you need from queries: specify which components you need to know about
- if you’re looking for entities that are within your worker’s checkout radius, search internally on the worker instead of using a query
For details on implementing entity queries, see the SDK-specific docs:
SpatialOS provides a success guarantee for commands: if a command response indicates that the command was executed successfully on the target worker, then it must be the case that the command was fully executed on the target worker, and that component updates sent in the command handler were applied by SpatialOS.
However, if commands are short circuited, then this property no longer holds. This is because it is possible for a worker to report that the short-circuited command succeeded despite the fact that updates sent by the command handler were dropped by SpatialOS, since the worker could have lost write access before the updates were delivered.
Commands are executed in the context of a distributed system, so it is important to note that reports of success and failure may differ from something like a local function call or REST API call.
Commands may fail for various reasons:
- If you try to invoke a command on an entity that doesn’t have the component that defines this command, then you will simply get back an error in your callback.
- If you try to invoke a command on an entity that does have the component that specifies this command, but you haven’t implemented any handlers to respond to incoming requests, then you will simply get back an error in your callback.
- A command may fail due to a write access transfer. For instance, suppose you send a command from a Unity worker authoritative over a particular component on a given entity. If your worker loses write access to the component before a command response is received, your command callback will immediately be invoked with an error message telling you so.