A SpatialOS project is the source code of a game that runs on SpatialOS. We often use this to refer to the directory that contains the source code, too.
A project includes (but isn’t limited to):
- The source code of all workers used by the project
- The project’s schema
- (optional) Snapshots of the project’s SpatialOS world
- Configuration files, mostly containing settings for deployments (for example, launch configuration files)
Your project name is a name which is used to label your project. It’s generated for you when you sign up
for SpatialOS. It’s usually something like
You must specify this name when you run a cloud deployment. You can either:
- set the name in the
spatialos.jsonfile in the root of your project
- pass the name to the spatial command-line tool every time you run
spatial cloud launch, using the flag
You can find out what your project name is in the Console.
An assembly is what’s created when you build. It contains all the files that your game uses.
When you run a cloud deployment, you have to specify an assembly to use.
spatial command-line tool (CLI)
Also known as the “
spatial command-line tool provides a set of commands that you use to interact with a
SpatialOS project. Among other things, you use it to:
- build the workers in your project
spatial worker build)
- deploy your game
spatial local launchor
spatial cloud launch)
- generate code from your project’s schema
spatial worker codegen)
- install software dependencies required for SpatialOS development
spatial setup install-dependencies)
- check you have the correct versions of software dependencies
- build using the command line with the command
spatial worker build <worker whose code changed>: for example,
spatial worker build MyCSharpWorker.
We recommend only building the bits of your project that you’ve changed, to save time. For example, if you’ve only changed the source code of one worker, you should only build that worker’s code.
You can build all workers in your project using the command
spatial worker build.
When you want to try out your game, you need to run a deployment of the game/project. This means launching SpatialOS itself. SpatialOS sets up the world based on a snapshot, then starts up the workers needed to run the game world.
Once the deployment is running, you can connect clients to it. You can then use the clients to play the game.
You can run a deployment:
Before you run a local deployment, you need to:
- Have a snapshot to be the starting point of your world.
- Build, if you’ve made any changes to your project/worker code.
You can launch a local deployment using the command
spatial local launch.
Before you can run a cloud deployment, you need to:
- Know your project name, and specify it (either in
spatialos.json, or pass it to
spatial cloud launchusing the argument
- Have a snapshot to be the starting point of your world.
- Build a new assembly, if you’ve made any changes to your project/worker code.
- Upload the assembly.
When you run the launch command, you specify:
- the name of the assembly to use
- the launch configuration file to use
- a label for the deployment (the deployment name)
- the snapshot to start from
Once the deployment is running, you can connect client-workers to it, using the command
spatial cloud connect external <deployment name>
Launch configuration file
A launch configuration file contains settings that the
spatial command-line tool
uses when it launches a deployment. This includes things like how big the world
is, which workers to use in the deployment, and what permissions to give them.
Easily confused with the launch configuration section in the worker configuration file (worker.json).
The Inspector is a web-based tool that you use to explore the internal state of a SpatialOS world. It gives you realtime view of what’s happening in a deployment, locally or in the cloud. Among other things, it displays:
- which entities are in the world
- what their components’ properties are
- which workers are connected to the deployment
- how much load the workers are under
The Launcher gets the executable for the client-worker from the assembly you uploaded.
The Locator is the SpatialOS service responsible for connecting a client-worker to a deployment.
From SpatialOS 13.5 onwards, client-workers can connect to both cloud and local deployments using the Locator. Previously, it was only possible to connect to cloud deployments.
- your project name
- running and previous cloud deployments using that project name
- all the assemblies you’ve uploaded using that project name
- a page for each deployment, which shows its status, and gives you access to the Inspector, Logs, and Metrics pages for that deployment.
Workers are programs that connect to a SpatialOS world. They perform the computation associated with a world: they can read what’s happening, watch for changes, and make changes of their own.
In order to achieve huge scale, SpatialOS divides up the entities in the world between workers, balancing the work so none of them are overloaded. For each entity in the world, it decides which worker should have write access to each component on the entity. (To prevent multiple workers clashing, ony one worker at a time can have write access to a component.)
As the world changes over time, where entities are and the amount of work associated with them changes. server-workers (also known as “managed workers”) report back to SpatialOS how much load they’re under, and SpatialOS adjusts which workers have write access to components on which entities (and starts up new workers when needed). This is called load balancing.
Around the entities they have write access to, each worker has an area of the world they are interested in. A worker can read the current properties of the entities within this area, and SpatialOS sends updates about these entities to the worker.
You can create workers using:
- the worker SDKs (in C++, C, Java, or C API)
- Unity - via the SpatialOS GDK for Unity
- Unreal - via the SpatialOS GDK for Unreal
Also known as “managed worker”, “server-side worker”.
A server-worker has its lifecycle managed by SpatialOS. That means in a running deployment, SpatialOS is in charge of starting it up and stopping it, as part of load balancing - unlike a client-worker.
Server-workers are usually tasked with implementing game logic and physics simulation.
You might have just one server-worker connecting to a SpatialOS world, or dozens, depending on the size of the world.
You tell SpatialOS how to launch a worker as a server-worker in its worker configuration file (worker.json).
Also known as “external worker”, “client-side worker”, or “client”.
You tell SpatialOS how to launch a worker as a client-worker in its worker configuration file (worker.json).
Unlike a server-worker, a client-worker’s lifecycle is not managed by SpatialOS. In a running deployment, there will be one client-worker per player, and the players start and stop their client-worker.
Client-workers are mostly tasked with visualising what’s happening in the world. You’d also use them for dealing with player input. In general, you want to give client-workers write access to as few components as possible, to make cheating difficult.
If you want to test what would usually be a server-worker by stopping and starting it manually in your game development environment, you can make that worker unmanaged in a local deployment or cloud deployment of your game. Note that these workers are not client-workers (external workers), even though client-workers are also not managed by SpatialOS. Unmanaged workers access the deployment in a different way to client-workers.
Worker attribute sets
In its bridge configuration, each worker type specifies an attribute that says what layer it belongs to, for example “physics”. This attribute is used in access control lists, which specify which attribute a worker type must have in order for instances of that worker type to get read or write access to a component.
Worker type is the label for a worker. It’s mostly important when running worker instances, so you know what
kind of worker it is. For example,
UnityClient are worker types.
Each worker type has a worker configuration file (
Sending an update
If a worker has write access to a component, it can send an update to it. An update can change the value of a property, or trigger an event. You can change multiple properties and trigger multiple events in one update.
Worker configuration (worker.json)
Each worker must have a worker configuration file, with the name
spatialos.MyCSharpWorker.worker.json. This file:
- sets the process used to build the worker
- configures settings to do with how the worker communicates with SpatialOS, including information like what components the worker is interested in
- sets whether a worker is a server-worker or aclient-worker
- for server-workers, tells SpatialOS how to run the worker in the cloud
- for client-workers, specifies how to launch the worker on the game player’s local computer
Load balancing only applies to server-workers.
When an instance of a worker is struggling with a high workload, SpatialOS can start up new instances of the worker, and give them write access to some components on entities.
This means that an entity won’t necessarily stay on the same worker instance, even if that entity doesn’t move. SpatialOS may change which components on which entities a worker instance has write access to: so entities move “from” one worker instance to another. Even though the entity may be staying still, the worker instance’s area of interest is moving.
There are three types of interest: entity interest, component interest, and query-based interest.
A worker is interested in all chunks that contain entities it has write access to a component on. It’s also interested in chunks within a configurable radius of those entities: this makes sure that workers are aware of entities nearby. You can set this radius in the worker configuration.
The consequence of a worker being interested in a chunk is that it will check out all the entities in that chunk.
Each worker, in its worker configuration (worker.json), specifies which components it is interested in. A worker will only get sent updates about components it’s interested in.
This means that, for entities inside a chunk that a worker is interested in, it may only be interested in (and therefore only check out) particular components on that entity.
The component delivery settings in a worker configuration specify which components a
worker is interested in. By default, a worker is only interested in the components with
explicitly set to
true in its worker configuration.
Which components a worker is interested can change at runtime:
- If a worker is given write access to a component, it becomes interested in that component.
- You can manually update which components a worker is interested in at runtime.
You enable query-based interest on individual entities, rather than universally. This means you can selectively enable query-based interest only on the entities for which you currently use streaming queries or component delivery settings. (You can enable it for all entities, but you don’t have to, because entity interest still works.)
- it will have a local representation of every entity in that chunk
- SpatialOS will send it updates about those entities
A worker will check out all chunks that it is interested in.
Streaming queries allow workers to get information about the world outside the region they’re interested in, so that they know about entities that they don’t have checked out (for example, entities that are far away, or that don’t have a physical position).
For more information on the advantages and limitations of streaming queries, go to Bridge configuration: streaming queries.
Worker flags let you change values that workers use, either at the start of a deployment or dynamically while it’s running. For example, you could vary the walking speed of your entities and see how this affects the world.
Worker flags (and their values) are defined in the launch configuration file.
Node refers to a single machine used by a cloud deployment. Its name indicates the role it plays in your deployment. You can see these on the advanced tab of your deployment details in the Console.
Also known as “the world” and “the game world”.
SpatialOS manages the world, keeping track of all the entities and what state they’re in.
Changes to the world are made by workers. Each worker has a view onto the world (the part of the world that they’re interested in), and SpatialOS sends them updates when anything changes in that view.
It’s important to recognise this fundamental separation between the SpatialOS world and the view/representation of that world that a worker checks out locally. This is why workers must send updates to SpatialOS when they want to change the world: they don’t control the canonical state of the world, they must use SpatialOS APIs to change it.
You can look at layers in two ways:
- A layer is a group of components on entities in the game world.
- A layer comprises the worker instances that have authority over one of those groups.
For details, see Layers.
You set the size of chunks for your world in launch configuration files.
- Launch configuration file: the
World units are an arbitrary unit that workers can interpret as they choose.
Settings in world units:
- the size of chunks is defined in world units
- the dimensions of the world
- the entity interest radius
- the radius of a query’s sphere
Queries can search for entities with the following attributes:
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
You should keep 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 region of interest, search internally on the worker instead of using a query
All of the objects inside a SpatialOS world are entities: they’re the basic building block of the world. Examples include players, NPCs, and objects in the world like trees.
Entities are made up of components, which store the data associated with that entity.
For example, for workers built using Unity, you might want to have a prefab associated with each entity type, and spawn a GameObject for each entity the worker has checked out.
You can have other objects that are not entities locally on workers - like UI for a player - but no other worker will be able to see them, because they’re not part of the SpatialOS world.
An entity is defined by a set of components. Common components in a game might be things like
PlayerControls. They’re the storage mechanism for data about the world that you
want to be shared between workers.
Components can contain:
- properties, which describe persistent values that change over time (for example,
- events, which are things that can happen to an entity (for example,
- commands that another worker can call to ask the component to do something, optionally returning
a value (for example,
Components are defined as files in your schema.
Properties are one of the things that can be contained in a component. Properties describe persistent values that change over time.
- Read the current value of a property
- Watch for changes to the value of a property
- Send an update to the value of a property (if they have write access)
- Watch for an event
- Send an update that triggers an event (if they have write access)
Commands are one of the things that can be contained in a component. They’re essentially a remote procedure call (RPC). Commands facilitate communication in the other direction to events and properties: they allow any worker to send a request to the worker with write access to a specific component. The receiving worker can take action and should respond to the request.
By default, commands are routed through SpatialOS.
Because which worker has write access to a component can change regularly, and commands must be sent to the worker with write access, commands can fail if this worker changes between the time of sending and the time of receiving.
This means that, for communication within a small area, it’s better to model it using properties or events. Commands are best suited when you don’t know where the target entity is, or know that it’s likely to be far away. You can short-circuit commands that you think will be received by the same worker that sent them, but that comes with a lot of caveats.
- Send a command to a component on an entity
- Respond to a command sent (if they have write access)
This comes with a lot of caveats, because if the worker loses write access to the component, the command can fail.
Note that there’s no reason that this component must be used to represent entity positions inside,
say, worker logic. For example, a 2D simulation could use a custom position component with only two
fields, and update
improbable.Position at a lower frequency to save bandwidth.
Metadata is a component in the standard schema library.
It has a single property,
entity_type, that’s used to label the entity.
Persistence is a component in the standard schema library. It’s optional, but all entities that you want to persist in the world must have this component. Persistence means that entities are saved into snapshots.
If an entity doesn’t have this component, it won’t exist in snapshots. This is fine for transient entities. For example, you probably don’t want the entities associated with players to be saved into a snapshot you take of a deployment, because the players won’t be connected when you restart the deployment.
- which types of workers have read access to an entity
- for each component on the entity, which type of worker have write access
Creating an entity template varies in different programming languages, but, in general, you create a new
Entity object, and then add components to it.
Read and write access (“authority”)
Many workers can connect to a SpatialOS world. To prevent them from clashing, only one worker instance at a time is allowed to write to each component on each entity: ie, given write access. Write access is sometimes also referred to as authority.
Which types of workers can have write access is governed by each entity’s access control list (ACL).
Which specific worker instance actually has write access is managed by SpatialOS, and can change regularly because of load balancing. However, the list of possible workers is constrained by the ACL.
ACLs also control which workers can have read access to an entity. Read access is at the entity level: if a worker can read from an entity, it is allowed to read from all components on that entity.
Live snapshots/taking snapshots
- extend the functionality of the game development kits for Unity or Unreal.
- create low-level workers for game logic that does not require a game engine; these could work without any game engine or with a game engine, complimenting the functionality of workers in any game engine, including Unity or unreal.
The worker SDK is availailable in several programming languages: The C++, C# and Java flavor have a very similar structure; the C API is lower-level and doesn’t include code generation.
C# worker SDK
C++ worker SDK
Java worker SDK
The lowest level took kit for developing SpatialOS workers.
Unity with SpatialOS
GDK for Unity
A Unity-native experience for developing games with SpatialOS. The GDK for Unity is a toolkit for developing workers using Unity, built on top of the C# worker SDK. It includes APIs for interacting with a SpatialOS world. See the GDK for Unity documentation.
SDK for Unity
Superseded by the GDK for Unity. Until SpatialOS 13.0, SpatialOS included the SDK for Unity. From SpatialOS 13.0 onwards, the SDK for Unity has been released separately.
Unreal with SpatialOS
GDK for Unreal
An Unreal-native experience for developing games with SpatialOS. The GDK for Unreal is a toolkit for developing workers using Unreal, built on top of the C++ worker SDK. It includes APIs for interacting with a SpatialOS world. See the GDK for Unreal documentation.
SDK for Unreal
Superseded by the GDK for Unreal. Until SpatialOS 13.0, SpatialOS included the SDK for Unreal. From SpatialOS 13.0 onwards, the SDK for Unreal has been released separately.