Understanding read and write access (“authority”)
SpatialOS locks down which workers can read from (and check out) an entity, and which can write to each of its components: ie, which have read and write access.
If a worker can’t read from an entity, it won’t have any knowledge of the entity, and won’t check it out.
This page explains how access works, and what aspects of read and write access you need to take into consideration as a developer.
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.
Worker attributes
In its bridge configuration, each worker has attributes that it sends to SpatialOS. For example, it says it has the “physics” attribute, or it says it’s 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.
Determining access at runtime
ACLs specify which worker types can have access, but not which worker instances actually do at any given time.
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 AuthorityLossImminent
state.)
Authority states
For a particular worker and a particular component, the worker’s authority can be in one of three authority states (represented by an enum):
NotAuthoritative
Authoritative
AuthorityLossImminent
The authority state can only transition from NotAuthoritative
to Authoritative
, Authoritative
to
AuthorityLossImminent
, and AuthorityLossImminent
to NotAuthoritative
.
Enabling and configuring AuthorityLossImminent
notifications
You can configure the time between AuthorityLossImminent
and NotAuthoritative
on a per-worker, per-component
basis using authorityHandoverTimeoutMs
in the
bridge configuration.
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:
Limitations
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.
Client-side authority
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.
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.