Hlapi FAQ

Frequently Asked Questions about the High-level networking API.

Networked Unity Objects

How do I create my own NetworkedBehaviour?

Like extending MonoBehaviour allows a script to integrate with Unity events and systems, extending a NetworkedBehaviour allows for integrating with the Hlapi. Each NetworkedBehaviour that is attached to a NetworkedUnityObject and is registered to that object’s Behaviours list (through the Editor) will automatically be initialized whenever that object is network spawned. This allows for registering NetworkedDataHandlers to the provided Group without having to worry about object lifetimes or tagging, as that will be handled by the Hlapi.

For example, the following script demonstrates implementing a NetworkedBehaviour that sets up Transform and Color replication. As each spawned NetworkedUnityObject has its unique NetworkGroup, writing to any of these NetworkedDataHandlers will only affect the corresponding object on other devices.

using System;
using Niantic.ARDK.Networking;
using Niantic.ARDK.Networking.HLAPI.Data;
using Niantic.ARDK.Networking.HLAPI.Object;
using Niantic.ARDK.Networking.HLAPI.Object.Unity;
using Niantic.ARDK.Utilities;
using UnityEngine;

[RequireComponent(typeof(AuthBehaviour))]
public sealed class SampleNetworkedBehaviour :
  NetworkedBehaviour
{
  [SerializeField]
  private TransformPiece _replicatedPieces = TransformPiece.All;

  // Reference to the material on the GameObject
  [SerializeField]
  private Material _material;

  private UnreliableBroadcastTransformPacker _transformPacker;
  private NetworkedField<Color> _networkedColorField;

  // Define an initializer that will be run as soon as the NetworkedUnityObject
  //   has been spawned
  protected override void SetupSession(out Action initializer, out int order)
  {
    initializer = () =>
    {
      NetworkedDataDescriptor authToObserverDescriptor =
        Owner.Auth.AuthorityToObserverDescriptor(TransportType.UnreliableUnordered);

      // Create an UnreliableBroadcastTransformPacker that
      //   replicates Position, Rotation, and Scale
      _transformPacker = new UnreliableBroadcastTransformPacker
      (
        "NetTransform",
        gameObject.transform,
        authToObserverDescriptor,
        _replicatedPieces,
        Owner.Group
      );

      _networkedColorField = new NetworkedField<Color>
      (
        "color",
        authToObserverDescriptor,
        Owner.Group
      );

      _networkedColorField.ValueChangedIfReceiver += OnColorFieldChanged;
    };

    order = 0;
  }

  // When this is called by the peer that has the role Authority, all
  //   Observing peers will receive a ValueChangedIfReceiver event
  private void UpdateColorForAllPeers(Color newColor)
  {
    _networkedColorField.Value = newColor;
  }

  private void OnColorFieldChanged(NetworkedFieldValueChangedArgs<Color> args)
  {
    Optional<Color> optionalValue = args.Value;
    if (!args.Value.HasValue)
    {
      return;
    }

    _material.color = args.Value.Value;
  }

  private void OnDestroy()
  {
    _transformPacker.Unregister();
    _networkedColorField.Unregister();
  }
}

What’s the NetworkedDataDescriptor used for?

The NetworkedDataDescriptor is a struct that contains information regarding authorized senders and receivers, as well as the networking protocol. Many of the prebuilt Hlapi NetworkedDataHandler require a NetworkedDataDescriptor on construction, to define the intended sending/receiving pattern of that handler.

The NetworkedDataDescriptorExtension provides a few boilerplate methods to generate commonly used patterns (Authority → Observers, Observers → Authority, and Any → Any).

Authority

What authority should a peer claim?

Authority is a distributed agreement for the role of each peer. The assigned role for each peer can either be Role.Authority, Role.Observer, or Role.None. In general, each instance of authority covers a single object, or a logical group of objects. For example, if each peer has an avatar that they control, they would each claim the role Authority over their avatar, and all other peers would claim the role Observer, to be notified of updates.

How does a peer claim authority?

A default implementation for replicating authority is provided by the GreedyAuthorityReplicator. For a NetworkedUnityObject with this component, only one peer can claim the role Authority at a time, while any number of peers can claim the role Observer. In order to change the Authority over an object, the current peer with role Authority must first claim a different role (most likely Observer), then the following peer can claim Authority once it receives the role update.

What’s the difference between AuthBehaviour and GreedyAuthorityReplicator?

The AuthBehaviour component provides Unity integration with the Authority APIs by wrapping the GreedyAuthorityReplicator class. This component supports selecting common starting role patterns (owned by host, or observer by default). If both are selected, “owned by host” will take precedence over “observer by default” for the host peer.

../../../_images/auth_behaviour.png

Is the GreedyAuthorityReplicator good enough?

When using the GreedyAuthorityReplicator, only one peer should have the role of Authority at a given time. However, the GreedyAuthorityReplicator currently only checks the locally known roles of peers before attempting to claim the role of Authority. If two peers attempt to simultaneously claim the role of Authority, it is possible for peers in the session to have conflicting knowledge regarding which peer is actually the Authority (a race condition occurs involving which peer’s claim arrives first).

For cases in which Authority rarely or deterministically changes hands (for example, a turn based game), the GreedyAuthorityReplicator is good enough.

Message Passing

How are messages sent?

The Hlapi is driven by the SendQueuedData method in the HlapiSession, which by default is called once per Unity Update loop. To manually control the frequency of calling SendQueuedData, create an HlapiSession through its constructor, rather than through GetOrCreateManagedSession.

When SendQueuedData is called, the HlapiSession will query each of the NetworkedGroups currently registered to it, which will in turn query each NetworkedDataHandler that is registered to the group. From there, each NetworkedDataHandler determines if it has some update to send over the network (for example, an updated position, or a new message) and returns the data as an object (or a specific object NetworkedDataHandlerBase.NothingToWrite).

Each NetworkGroup will then package the data and pass it up to the HlapiSession, where it is collated, appended with the required metadata, serialized, and sent over the network to the relevant peers.

The above process is run once per peer in the session, and each NetworkedDataHandler determines if it has some data to send to that peer. This allows for various peers to selectively receive or send some messages, instead of sending all data to all peers.

How are messages received?

When the Hlapi receives a message with the Hlapi message tag, it assumes that the message is data packaged in the above form, unpacks the group data pieces contained in the message, and sends them to the correct NetworkGroup. If a message is received that is addressed to an NetworkGroup that has not yet been registered to the HlapiSession, the message will be cached and handled once that NetworkGroup registers (but only if the TransportType is reliable; unreliable messages will be dropped).

From there, the NetworkGroup does a similar unpacking and addressing of messages to its registered NetworkedDataHandlers (and caching messages to unknown handlers, if reliable). Finally, the NetworkedDataHandlers will receive the message that was sent by their counterpart, from another device, and do something with that data. For example, the UnreliableBroadcastTransformPacker knows that all data received will be a PackedTransform, containing an updated position for its GameObject, while the GreedyAuthorityReplicator knows that it is receiving an attempted Role claim from a peer.

How are Hlapi messages serialized?

The Hlapi uses the GlobalSerializer system that is provided with ARDK.

See Also

Low level networking

The high level networking API (Hlapi)