Skip to main content

ServiceManager

sealed class Unity component singleton static
public sealed class ServiceManager : Singleton<ServiceManager>

Inherits: Singleton<ServiceManager> — a MonoBehaviour base. Reach the live instance with ServiceManager.Instance.

The connection entry-point of the SDK. Drop one on a GameObject and it stands up the SDK's local service host, performs discovery, and tracks which remote components (CVS, calibration, camera feed, etc.) are connected. It connects on Start() — there is no public Connect() — so placing the component in the scene (with discovery succeeding) is what establishes the connection. Once started, reach the live connection through the static Server. Connection state is exposed through static properties so any code can poll it without holding a reference.

Units

The AR 51 Unity SDK works in meters (positions/lengths) and degrees (angles). ServiceManager itself is connection plumbing and exposes no spatial values, but everything it connects you to (skeletons, cameras, objects) reports meters.

How-to

This page is reference (facts only). For the step-by-step connect → skeleton → character walkthrough, see the How-to guide.

Properties

Static connection state

These are static — poll them from anywhere to gate service-dependent logic.

PropertyTypeAccessDescription
Connection
ServerServiceContainerget (private set)the running server/connection container (transport assembly); null until startup completes. Use it to reach SkeletonProvider, ConnectedComponents, GetCameraFeedClient, etc.
IsConnectedboolgettrue when the underlying server is up and connected — poll this first before issuing service calls
IsCvsConnectedboolgettrue when at least one main CVS server component is in the connected set; gate skeleton-dependent UI/logic on this
IsCalibrationConnectedboolgettrue when a CVS calibration component is connected

Inspector configuration

Set these in the Inspector (or in code before Start) to configure discovery, ports, platform identity, and whether this instance acts as a dedicated game server (DGS).

FieldTypeDefaultDescription
Logging
LogRequestsboolfalseverbose request logging
Dispatch
MaxQueueSizeint100Unity-thread dispatch queue cap
Identity
PlatformPlatformTypeauto-set to the running platform
HandProviderHandProviderTypewhich hand-tracking provider to use
BatteryLevelfloat0-1 = use system battery; 0..100 override
Dedicated game server
IsDedicatedGameServerboolfalserun this instance as a DGS
DedicatedOmsAddressstring""explicit OMS address for DGS
Discovery & ports
DiscoveryPortintUDP discovery port
UseRandomServicePortbooltruepick a free TCP port for the local service
ServicePortintexplicit local service port when UseRandomServicePort is false
RunOMSboolfalsehost an embedded OMS in-process
KeepAliveTimeoutInMillisintlivelihood / keep-alive timeout (ms)

Timeline override (advanced / playback)

MemberTypeAccessDescription
EnqueueTimeSecondsdoublegetcurrent enqueue clock (seconds)
OverrideTimeSecondsdoublefieldoverridden clock value; leave at the -1 default for live use
OverrideTimeDelaySecondsdoublefieldadded delay against the overridden clock
⚠️ needs confirmation

The timeline-override surface (OverrideTimeSeconds, EnqueueDelayedMessages, IsEnqueueRequired) is intended primarily for internal playback timing, not general app use. Most callers leave the override fields at their -1 defaults.

Method summary

Static — discovery

MethodReturns
GetMainServerComponentsIEnumerable<ComponentDescriptor>static
FindComponentByServiceComponentDescriptorstatic
FindComponentsByServiceComponentDescriptor[]static
WaitForServiceTask<ComponentDescriptor[]>static · async

Instance — connection control

MethodReturns
Reconnectvoid
Disconnectvoid

Instance — timeline (advanced)

MethodReturns
IsEnqueueRequiredbool⚠️ playback
EnqueueDelayedMessagesvoid⚠️ playback

→ Full descriptions in Method details below.

Events

Standard .NET events (subscribe with +=). Bind these on the instance (ServiceManager.Instance).

EventSignatureFires when
OnStartedEventHandler OnStartedthe service host has started and Server is available — the signal that the connection is up
OnRegistrationChangedEventHandler OnRegistrationChangedthe set of connected/registered components changes (a component joined or left) — subscribe to refresh your component list

Method details

GetMainServerComponents

methodstatic
public static IEnumerable<ComponentDescriptor> GetMainServerComponents();

The connected CVS server components.

ReturnsIEnumerable<ComponentDescriptor>the main CVS server components, empty when none are connected

FindComponentByService

methodstatic
public static ComponentDescriptor FindComponentByService(string serviceName);

Find the first connected component advertising a given service name. Use the returned descriptor's Ip / Port / GetEndpoint() to connect.

Parameters
serviceNamestringa service name constant from ServiceNames (e.g. ServiceNames.SkeletonService)
ReturnsComponentDescriptorthe first matching component, or null if none is connected
Exampleinferred
var cam = ServiceManager.FindComponentByService(ServiceNames.CameraFeedService);
if (cam != null)
{
var feed = ServiceManager.Server.GetCameraFeedClient(cam.Ip, cam.Port);
// … register a listener on `feed`
}

FindComponentsByService

methodstatic
public static ComponentDescriptor[] FindComponentsByService(string serviceName);

Find all connected components advertising a given service name.

Parameters
serviceNamestringa service name constant from ServiceNames
ReturnsComponentDescriptor[]every matching component, or an empty array if none is connected

WaitForService

methodstaticasync
public static async Task<ComponentDescriptor[]> WaitForService(
string serviceName,
CancellationToken token = default,
float millisecondsTimeout = float.MaxValue);

Awaitable discovery: polls until a component offering serviceName appears (or the token cancels / the timeout elapses), then returns all matching components. Call this after the manager has started to wait for a CVS/skeleton service to come online, instead of polling FindComponentByService yourself.

Parameters
serviceNamestringa service name constant from ServiceNames
tokenCancellationTokencancels the wait early; defaults to default (no cancellation)
millisecondsTimeoutfloatgive-up time in milliseconds; defaults to float.MaxValue (wait indefinitely)
ReturnsTask<ComponentDescriptor[]>all components offering the service once one appears; an empty array if the timeout elapses or the token cancels first
Exampleinferred
// Wait (up to 5 s) for the skeleton service after the manager starts, then read its endpoint.
async void Start()
{
ServiceManager.Instance.OnStarted += async (s, e) =>
{
var components = await ServiceManager.WaitForService(
ServiceNames.SkeletonService,
this.GetCancellationTokenOnDestroy(), // ⚠️ cancellation source depends on your setup
millisecondsTimeout: 5000f);

if (components.Length == 0)
Debug.LogWarning("Skeleton service did not come online in time");
else
Debug.Log($"Skeleton service at {components[0].GetEndpoint()}");
};
}

Reconnect

methodinstance
public void Reconnect();

Resume the connection (restarts the server). Internally tied to application-pause handling — the SDK calls it when the app resumes — but you can call it after a manual Disconnect.

Disconnect

methodinstance
public void Disconnect();

Pause the connection by shutting the server down and stopping discovery. Pair with Reconnect to bring it back. There is no public Connect() — the initial connection happens automatically on Start().

IsEnqueueRequired

methodinstance
public bool IsEnqueueRequired(double timestamp);

Whether an incoming message at timestamp must be queued against the overridden clock rather than dispatched immediately.

Parameters
timestampdoublea message timestamp, seconds since the Unix epoch
Returnsbooltrue if the message should be enqueued for delayed dispatch
⚠️ needs confirmation

Part of the internal playback-timing surface; not intended for general app use.

EnqueueDelayedMessages

methodinstance
public void EnqueueDelayedMessages(double timestamp, Action action, string caller = null);

Queue action to run when the overridden clock reaches timestamp.

Parameters
timestampdoubletarget dispatch time, seconds since the Unix epoch
actionActionwork to run at that time
callerstringoptional diagnostic label for the caller
⚠️ needs confirmation

Part of the internal playback-timing surface; not intended for general app use.

See also

Was this page helpful?