Sites

Menu
These are the docs for 14.3, an old version of SpatialOS. 14.5 is the newest →

Handling data received from SpatialOS

All code examples in this section assume using Improbable.Worker.CInterop; and using Example; (the generated code namespace).

Processing operations

It is up to you to decide how the basic event loop of receiving data from SpatialOS should be structured, depending on the worker’s requirements.

The worker needs to:

  1. Call Improbable.Worker.CInterop.Connection.GetOpList to get a list of “operations” (for example entity creation, or a component update) that have been received since the last time the function was called.
  2. Process the Improbable.Worker.CInterop.OpList using hand-written serialization code, or using custom codegen.

If you provide a positive timeout (in milliseconds) to GetOpList, the function will block until there is at least one operation to return, or until the timeout has been exceeded.

If the connection fails (when Connection.IsConnected() == false), any error messages explaining the cause will be returned by GetOpList(). Make sure to process this list in order to receive all available diagnostic information.

In order to detect that a worker is still responsive, SpatialOS sends periodic heartbeat requests. Responding to these happens automatically, but the buffer for incoming operations can fill up with other messages. If that happens, the heartbeats cannot be processed and your worker may be killed. Therefore, you should make sure that your receive buffer doesn’t fill up faster than you can call GetOpList.

Example of processing operations

The following snippet shows a simple example implementation of an event loop that processes operations from SpatialOS 60 times per second:

const int FramesPerSecond = 60;

private static void RunEventLoop(Connection connection)
{
  var maxWait = System.TimeSpan.FromMilliseconds(1000f / FramesPerSecond);
  var stopwatch = new System.Diagnostics.Stopwatch();
  while (true)
  {
    stopwatch.Reset();
    stopwatch.Start();
    var opList = connection.GetOpList(0 /* non-blocking */);
    ProcessOpList(opList);
    // Do other work here...
    stopwatch.Stop();
    var waitFor = maxWait.Subtract(stopwatch.Elapsed);
    System.Threading.Thread.Sleep(waitFor.Milliseconds > 0 ? waitFor : System.TimeSpan.Zero);
  }
}

private static void ProcessOpList(OpList opList)
{
  var opCount = opList.GetOpCount();
  for (var i = 0; i < opCount; ++i)
  {
    OpType opType = opList.GetOpType(i);

    switch (opType)
    {
      case OpType.Disconnect:
        var disconnectOp = opList.GetDisconnectOp(i);
        System.Console.Error.WriteLine(disconnectOp.Reason);
        break;

      case OpType.ComponentUpdate:
        ProcessComponentUpdate(opList.GetComponentUpdateOp(i));
        break;

      case OpType.Metrics:
        ProcessMetrics(opList.GetMetricsOp(i));
        break;

      // handle other ops
    }
  }
}

Caveats about receiving component updates

Note that the component updates:

  • can be partial, i.e. only update some properties of the component
  • do not necessarily have to contain data that is different from the worker’s current view of the component
  • could have been sent by SpatialOS rather than a worker for synchronization purposes

OpType reference

OpType Received when… Parameter type
Disconnect The Connection is no longer connected and can no longer be used.
Check the log for errors relating to the disconnection.
DisconnectOp
FlagUpdate A worker flag has been created or deleted, or its value has changed. FlagUpdateOp
LogMessage The SDK issues a log message for the worker to print. This does not include messages sent using Connection.SendLogMessage. LogMessageOp
Metrics The SDK reports built-in internal metrics. MetricsOp
CriticalSection A critical section is about to be entered or has just been left. CriticalSectionOp
AddEntity An entity is added to the worker’s view of the simulation. AddEntityOp
RemoveEntity An entity is removed from the worker’s view of the simulation. RemoveEntityOp
ReserveEntityIdsResponse The worker has receives a response for the reservation of an entity ID range it requested. ReserveEntityIdsResponseOp
CreateEntityResponse The worker receives a response for an entity creation it requested. CreateEntityResponseOp
DeleteEntityResponse The worker receives a response for an entity deletion it requested. DeleteEntityResponseOp
EntityQueryResponse The worker receives a response for an entity query. EntityQueryResponseOp
AddComponent A component is added to an entity in the worker’s view of the simulation. AddComponentOp
RemoveComponent A component is removed from an entity in the worker’s view of the simulation. RemoveComponentOp
AuthorityChange The worker’s write access authority state over a component changes (to Authoritative, Not Authoritative or Authority Loss Imminent). AuthorityChangeOp
ComponentUpdate A component on an entity in the worker’s view of the simulation is updated. ComponentUpdateOp
CommandRequest The worker receives a command request for a component on an entity over which it has write access authority. CommandRequestOp
CommandResponse The worker receives a command response for a command request. CommandResponseOp

Critical sections

Critical sections are a legacy feature. They do not provide any guarantees, and you should not use them. You cannot make any assumptions about whether any updates or operations arrive inside or outside critical sections.

Worker flags

To access the value of a worker flag, use the Connection.GetWorkerFlag() method:

const double DefaultWorkSpeed = 10;

private static void GetSpeedWorkerFlag(Connection connection)
{
  var speedFlag = connection.GetWorkerFlag("mycompany_theproject_speed");
  if (speedFlag != null)
  {
    SetWorkSpeed(System.Convert.ToDouble(speedFlag));
  }
  else
  {
    SetWorkSpeed(DefaultWorkSpeed);
  }
}


————
2019-11-25 Page added without editorial review.

Search results

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums