Skeleton
public sealed class Skeleton
Namespace: AR51.Unity.SDK (transport assembly, separate from .Client).
The per-frame skeleton payload the client receives from CVS. One Skeleton is one tracked track's pose for one frame: an identity (Id / AnchorId), capture/receive timestamps, optional head rotation and wrist positions, and a packed float buffer of joint positions you read through the generic getters. SkeletonConsumer maintains one Person per Id and feeds it the latest Skeleton.
You don't normally construct it; you receive it from SkeletonConsumer events (OnSkeletonReceived / OnCvsSkeletonReceived) as SkeletonEventArgs.Skeleton, or read the most recent one from Person.LastSkeleton.
Joint and wrist positions are Unity world-space meters; HeadLocalRotation is a Quaternion. Request Vector3 from the generic getters (GetPositions<Vector3>()) to get Unity world-space meters directly.
Positions arrive as a packed byte[] buffer. Don't unpack them by hand — call GetPositions<Vector3>() (and the hand getters) to decode into Unity types. Joint indices into the returned array follow the Joints constants.
Fields
| Field | Type | Description |
|---|---|---|
| Identity | ||
Id | string | skeleton / track id — the per-track identifier (the "PersonId"); the key SkeletonConsumer stores its Person under |
AnchorId | string | spatial anchor this skeleton is expressed in ("" / null = world) |
DeviceId | string | originating device id |
Source | Sources | where the frame came from — Sources.CVS or Sources.Other |
skeletonReply | SkeletonReply | underlying proto reply (entity id/name, confidence) — transport type |
CharacterPrefab | string | optional prefab name the server requests for this skeleton |
| Timing | ||
CaptureTimestamp | double | capture time at CVS — seconds since Unix epoch (1970 UTC) |
ReceivedTimestamp | double | local receive time — seconds since Unix epoch (1970 UTC) |
| Head & wrists | ||
HasHeadLocalRotation | bool | true when HeadLocalRotation is present |
HeadLocalRotation | AR51.Core.Quaternion | fused device head rotation (Core type — convert with Extensions) |
HasWristPositions | bool | true when the wrist positions are present |
LeftWristPosition | AR51.Core.Vector3 | left wrist position — meters (Core type) |
RightWristPosition | AR51.Core.Vector3 | right wrist position — meters (Core type) |
| Controllers | ||
MultiControllerInfo | MultiControllerInfoRequest | VR controller info — transport type (see Hands, controllers & boundary) |
| Playback override | ||
OverridePositions | byte[] | override the packed positions buffer (used by playback) — { get; set; } |
public static readonly Skeleton Empty; — the empty/no-op skeleton sentinel.
Id is the skeleton / track id — present from the first frame, stable for the life of the track, and the key under which SkeletonConsumer stores its Person. It is not the recognized identity: skeletonReply.EntityId (and EntityDisplayName) is the identified entity, populated only once the skeleton is recognized. Test it with Extensions.IsIdentified(); SkeletonConsumer.IgnoreUnidentified uses the same check.
Core.Vector3 / Core.Quaternion are transport (AR51.Core) types, not UnityEngine types — convert them with the Extensions helpers. Prefer the generic getters below, which already return Unity types when you request Vector3.
Constructors
| Constructor | Use |
|---|---|
Skeleton(SkeletonReply skeleton) | wrap a received proto reply (the normal CVS path) |
Skeleton(double captureTime, string id, string anchorId, byte[] rawPositions, …) | build from raw packed buffers — playback / synthetic sources; optional deviceId, characterPrefab, and raw left/right hand position & rotation buffers |
Method summary
Positions — generic decoders over the packed buffers; call with Vector3 for Unity world-space meters.
| Method | Returns | |
|---|---|---|
GetPositions<T> | T[] | body joints (indices follow Joints) |
GetLeftHandPositions<T> | T[] | left-hand joint positions |
GetRightHandPositions<T> | T[] | right-hand joint positions |
GetLeftHandRawPositions<T> | T[] | left-hand raw (pre-fuse) positions |
GetRightHandRawPositions<T> | T[] | right-hand raw (pre-fuse) positions |
Rotations
| Method | Returns | |
|---|---|---|
GetLeftHandRotations<T> | T[] | left-hand joint rotations |
GetRightHandRotations<T> | T[] | right-hand joint rotations |
Other
| Method | Returns | |
|---|---|---|
ToString | string |
→ Full descriptions in Method details below.
Method details
GetPositions
public T[] GetPositions<T>() where T : struct;
Decodes the packed body-joint buffer into an array of T. Pass Vector3 to get Unity world-space positions in meters. The returned array is indexed by the Joints constants (OpenPose-25 body layout, plus hands when present) — e.g. positions[Joints.Neck], positions[Joints.LWrist].
consumer.OnSkeletonReceived += (s, e) =>
{
Vector3[] joints = e.Skeleton.GetPositions<Vector3>(); // world-space meters
Vector3 neck = joints[Joints.Neck];
Vector3 lWrist = joints[Joints.LWrist];
Debug.Log($"{e.Skeleton.Id}: neck at {neck} (m)");
};
Hand positions
public T[] GetLeftHandPositions<T>() where T : struct;
public T[] GetRightHandPositions<T>() where T : struct;
public T[] GetLeftHandRawPositions<T>() where T : struct; // pre-fuse / un-smoothed
public T[] GetRightHandRawPositions<T>() where T : struct;
Per-hand joint positions, decoded like GetPositions<T>(); request Vector3 for Unity world-space meters. The …Raw… variants return the un-fused source positions (before head/wrist fusion and smoothing). Hand-joint order follows the hand indices in Joints (starting at Joints.RightWrist = 25).
Vector3[] left = skeleton.GetLeftHandPositions<Vector3>();
Vector3[] right = skeleton.GetRightHandPositions<Vector3>();
// or the fused wrist shortcut, when present:
if (skeleton.HasWristPositions)
{
Vector3 lw = skeleton.LeftWristPosition.ToUnity(); // Core.Vector3 → meters, via Extensions
}
Hand rotations
public T[] GetLeftHandRotations<T>() where T : struct;
public T[] GetRightHandRotations<T>() where T : struct;
Per-hand joint rotations. Request Quaternion for Unity rotations. Indexed in the same hand-joint order as the hand position getters.
Quaternion when T is Quaternion)ToString
public override string ToString();
Human-readable summary of the skeleton (id and key fields) for logging/debugging.
See also
Joints— the index map for every array the position getters returnPerson— the tracked-person wrapper that holds the latestSkeleton(LastSkeleton) and decodedPositionsSkeletonConsumer— receivesSkeletonframes and raises the events that hand you oneExtensions—IsIdentified()plusCore↔UnityVector3/Quaternionhelpers- Skeletons & Characters — the area overview and the Connect → skeleton → character sequence
- Class index — all Unity SDK types