Understanding read and write access (“authority”)
This page explains how that works, and what aspects of read and write access you need to take into consideration as a developer.
Note: Write access is also known as authority. The terms are used interchangeably.
Thinking about access
In order to read from a component, or make changes to a component, workers need to have access.
Ability to have access
You determine which type of worker can have which type of access using an entity’s access control list (ACL).
The ACL is a component that every entity has; for each of the entity’s components, it specifies which workers may be allowed to write to them, and which to read. You can read and manipulate this component in the same way as any other component.
In its bridge configuration, each worker has attributes that it sends to SpatialOS. For example, it says it’s a Unity worker (it has the “physics” attribute), or a player client (it has the “visual” attribute). SpatialOS uses these attributes to work out what components a worker can have access to.
These attributes are referenced in the access control list. There, you specify what attributes a worker must have to be able to read from an entity, and to write each of its components.
More about access control lists
The ACL determines:
- which types of workers can see an entity, and read its components
- for each component on the entity, which type of worker can write to it
For example: position is usually simulated on a physics worker, so we want to give a physics worker write access to the position component. An instance of the physics worker will have write access to the component, and while it has write access, it has complete control over the component. Nothing else can change the position of that entity.
See the example ACLs in the language-specific docs:
Determining access at runtime
ACLs specify which worker types can have access, but not which worker instances actually do at any given time.
Only one worker at any one time can have write access to a component. This prevents simultaneous changes putting the world into an inconsistent state.
This is known as the single writer principle.
Which specific worker instance actually has write access is managed by SpatialOS at runtime.
The load balancing configuration controls how the runtime decides which particular worker becomes authoritative over a particular component.
Handing over write access/authority between workers
During the lifecycle of a SpatialOS deployment, authority over a component can pass between different workers. This could happen if the ACL of a component changes, if load-balancing switches which worker is authoritative, or if the entity moves into another worker’s authority region.
Due to the latency between the runtime and workers, this can cause updates to be lost:
To mitigate this, there’s a callback which can notify a worker when it’s about to lose authority:
You can use this to send important updates before the worker loses authority.
Additionally, a worker can send a notification that it’s ready to lose authority:
(Note: This can only be done when the component is in the
For a particular worker and a particular component, the worker’s authority can be in one of three authority states (represented by an enum):
The authority state can only transition from
Enabling and configuring
You can configure the time between
NotAuthoritative on a per-worker, per-component
authorityHandoverTimeoutMs in the
By default, the timeout is set to 0: ie there’s no time for workers to send updates.
At minimum, you should set the timeout to the round trip time between the runtime and the worker. If it’s less than this, updates might still be dropped:
The feature to provide
AuthorityLossImminent notifications has the following known limitations:
- Setting an authority handover timeout will also cause the initial authority of a component (when an entity is first spawned) to be delayed by the authority handover timeout.
In an online game, you often want to give control of some components to the client.
For example, you could model user input as changes to a
PlayerControlsComponent that contains, as properties or events,
all the actions a user might make.
You could also choose to give the client control over other components, like their player entity’s position. This can help compensate for network latency. To do this, give write access on the component to the particular client that controls the player entity.
Note that giving write access to a player’s position to that player’s client can have unintended consequences, as this opens the possibility of a rogue client using this write access for its own advantage, for example making the player move faster than the game logic allows, or able to pass through walls. There are more involved techniques that can be used to compensate for network latency while not giving clients more access than they need, such as Client-Side Prediction.
You can change which worker has write access to a component at runtime. This means you can switch between server-side and client-side control by updating an entity’s ACL component.
All workers must have write access to at least one component.