Try SpatialOS

Sites

Menu
You are viewing the docs for 12.1, an old version of SpatialOS. 13.0 is the newest →

Bridge configuration

The bridge field of the worker configuration file specifies the worker’s runtime settings. It has the following overall structure:

"bridge": {
    "worker_attribute_set": {},
    "entity_interest": {},
    "streaming_query": [],
    "component_delivery": {},
    "component_settings": {}
}

Worker attribute sets

Required field.

A worker attribute set describes a worker’s capabilities, used to work out which components the worker can have access to, as a list of free-form strings. See the worker attributes page for details.

For example, a UnityWorker would have the following attribute set:

"worker_attribute_set": {
    "attributes": ["physics"]
}

In addition to the attribute set defined here, each worker automatically has the attribute "workerId:<worker ID>". For example, the worker UnityWorker12 would have the attribute "workerId:UnityWorker12" added to it.

Entity interest

Required field.

The entity interest field is about defining which entities a worker gets component updates for.

If a worker is authoritative over an entity, it gets an update whenever that entity’s components change. But it also needs to know about the entities nearby.

By default, workers get component updates for all entities they’re authoritative over, as well as for all other entities in the same chunk (the grid squares of a SpatialOS world). But chunks are square, and so this doesn’t quite work.

You can use the entity interest field to set a radius (in world units, see note below). This is a radius around entities that a worker is authoritative over. If there’s another chunk with any point inside this radius, the worker will get component updates for entities inside that chunk.

For example, to make sure a worker gets updates from entities within 10 world units of any entity the worker has write access to, use the following entity_interest setting:

"entity_interest": {
    "range_entity_interest": {
        "radius": 10
    }
}

Positions and distances are expressed in an arbitrary unit called “world unit”. It is up to the workers that run the simulation to interpret them consistently. Unity workers, for example, interpret one world unit as one meter in the Unity coordinate space.

Streaming queries

Optional field.

SpatialOS is based on the concept that workers are generally only interested in the entities they’re authoritative over, and any other entities that are nearby (within the entity interest radius). For example, a player might need to see entities up to 50m away from them, but doesn’t need to care about entities further away.

This is usually fine. But sometimes, you need information about other entities - for example, entities that are far away, but that should still be visible (such as mountains), or entities that you need to communicate globally but that aren’t physically located anywhere (for example, a global weather system). To get a worker to receive updates to these entities, you can use streaming queries.

If you want information about an entity, but you don’t need regular updates about it, use a query instead.

But if you need regular updates about an entity, it’s better to use streaming queries: they return information periodically, and they only return the new information about a component, rather than all the information about it.

Using streaming queries is similar to checking out, in that the worker will have a local representation of an entity, and will receive updates about it. A worker will have a local representation of entity X if you’ve set up a streaming query for component Y, and entity X has component Y. The worker will receive updates to this entity’s components at specific time intervals.

Limitations

Streaming queries have some limitations:

  • The worker won’t receive all of the updates for each component of an entity (the updates it receives will depend on the time interval you set), and it won’t receive any event updates
  • You can only set the time interval globally for all streaming queries within a deployment
  • You can’t change streaming queries at runtime
  • You have to specify components to query, rather than entities

Setting up a streaming query

First, you need to pick a component. By default, for every entity with that component, a streaming query will return updates to all components on that entity. However, it’s good practice to improve efficiency and bandwidth use by narrowing down which updates are returned.

To do this, specify:

  • which components (on the entities returned by the streaming query) you want updates for
  • a radius (around entities that a worker is authoritative over) that an entity must be within

For example, the following snippet will send this worker:

  • updates to the components your.game.Status, your.game.Health, and your.game.Flammable for all entities with the component your.game.GloballyVisible
  • updates to all components from all entities with the component your.game.HighlyVisible, within a radius of 1000 world units around an entity that the worker is authoritative over
"streaming_query": [
    {
        "global_component_streaming_query":{
            "component_name":"your.game.GloballyVisible"
    },
    "components_streamed": {
        "specific_components": {
            "components": [
                "your.game.Status",
                "your.game.Health",
                "your.game.Flammable"
                ]
            }
        }
    },
    {
    "bounded_component_streaming_query": {
        "component_name":"your.game.HighlyVisible",
        "radius":1000
        }
    }
]

Configuring the time interval

To configure the time interval between streaming queries, set streaming_query_interval in your launch configuration file.

The default time interval is 4 seconds.

Component delivery

Optional field.

This field configures the set of components a worker checks out when they check out an entity, and whether component updates are allowed to be sent in an unreliable manner.

By default:

  • only components with checkout_initially set to true are sent to the worker
  • the transmission for all component updates is RELIABLE_ORDERED

Components to check out initially

To specify the set of components a worker will get when they check out an entity, use the following fields of component_delivery:

  • checkout_all_initially (boolean). By default, this is set to false, which means only the components with checkout_initially set to true are sent to the worker when it checks out an entity.

    If set to true, all components are sent to the worker when it checks out an entity.

  • override maps fully-qualified component names to component delivery settings.

    Components without an override use the default message delivery settings as specified in the default field. They are only checked out initially if checkout_all_initially is true.

The 4 permutations of these settings for a particular component C therefore lead to the following behaviour:

  1. checkout_all_initially is false or isn’t specified and the checkout_initially override is false or isn’t specified for C - C is not checked out
  2. checkout_all_initially is true and the checkout_initially override is false or isn’t specified for C - C is checked out
  3. checkout_all_initially is false or isn’t specified and the checkout_initially override is true for C - C is checked out
  4. checkout_all_initially is true and the checkout_initially override is true for C - C is checked out

Individual component overrides only have an effect when checkout_all_initially is false or isn’t specified.

The worker can also change the set of components it is interested in at runtime - see the API documentation (C++, C#, Java) for more details.

Transmitting component updates unreliably (“quality of service”)

Component updates can be transmitted reliably or unreliably.

To prevent workers getting overloaded, you can choose to transmit some component updates unreliably. Quality of service describes the concept in more detail.

The default field of component_delivery sets the default way to transmit component updates. This can be either RELIABLE_ORDERED or UNRELIABLE_ORDERED.

This configuration applies only to messages sent to workers, not for messages sent from workers.

Examples

This example reliably transmits updates for all components except Position and Rotation, and mandates that the position component is checked out initially:

"component_delivery": {
    "default": "RELIABLE_ORDERED",
    "override": {
        "improbable.Position": {
            "checkout_initially": true,
            "message_delivery": "UNRELIABLE_ORDERED"
        },
        "mygame.coordinates.Rotation": {
            "message_delivery": "UNRELIABLE_ORDERED"
        }
    }
}

This example mandates that all components are checked out initially (using checkout_all_initially). Setting checkout_all_initially to true takes precedence over the individual components’ checkout_initially settings, so we don’t specify them:

"component_delivery": {
    "default": "RELIABLE_ORDERED",
    "checkout_all_initially": true,
    "override": {
        "improbable.Position": {
            "message_delivery": "UNRELIABLE_ORDERED"
        },
        "mygame.coordinates.Rotation": {
            "message_delivery": "UNRELIABLE_ORDERED"
        }
    }
}

Note that the initial checkouts of mygame.coordinates.Position and mygame.coordinates.Rotation components are not affected by the UNRELIABLE_ORDERED message delivery setting. Only subsequent updates will be unreliable.

Component settings

The component settings field allows you to configure various component settings. For now this allows you to set the authority handover timeout period. For more information, see Handing over authority between workers.

The component settings field allows you to configure settings for each individual component or configure a default which is applied to all other components. Below is an example of a typical configuration.

"componentSettings": {
    "perComponentSettings": {
        "improbable.MyFancyComponent": {
            "authorityHandoverTimeoutMs": 300
        }
    },
    "default": {
        "authorityHandoverTimeoutMs": 400
    }
}

In the example above, improbable.MyFancyComponent will have an authorityHandoverTimeoutMs of 300 and all other components will default to 400.

If no default is set, components will default to having an authorityHandoverTimeoutMs of 0.

Information about what the authorityHandoverTimeoutMs does can be found in Handing over authority between workers.

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums