Utility extensions
This page groups the SDK's broadly-used helper types: the Extensions static class (identification, camera-info accessors, Core↔Unity math conversion, logging) and four standalone utilities — ObjectFieldExtensions, TextureExtensions, AnimationTimer, and BiDictionary<T1,T2>.
All spatial conversions on this page are in meters (Unity world-space). The ToUnity/ToCore helpers convert between AR 51 Core math types and Unity types without rescaling — both sides are meters.
Extensions
static classpublic static class Extensions
Namespace: AR51.Unity.SDK
The SDK's broadly-used extension helpers. This page documents the members app developers call: skeleton identification, camera-info accessors, Core↔Unity math conversion, and logging. Array/marshalling helpers (ToArray, ToVector3, ToMatrix4x4, ToVector3Array, ToMatrix4x4Array, EfficientReverse, ReadExact, …) are also public but are low-level transport plumbing.
IsIdentified
public static bool IsIdentified(this SkeletonReply skeletonReply);
Returns true when the skeleton has been matched to a known entity — i.e. its EntityId is non-null, non-empty, and not "-1". Use it to filter to recognized people; SkeletonConsumer's IgnoreUnidentified uses this internally.
true if the skeleton is matched to a known entity// Only react to recognized people
if (skeletonReply.IsIdentified())
DoSomethingWith(skeletonReply.EntityId);
GetEndpoint
public static string GetEndpoint(this ComponentDescriptor c);
Formats a component descriptor's address as "ip:port" — the string form the services connect with.
"ip:port"Camera-info accessors
public static Matrix4x4 GetIntrisic(this CvsCameraInfo info); // intrinsic 4x4
public static Matrix4x4 GetExtrinsic(this CvsCameraInfo info); // extrinsic (world pose), handedness-corrected
public static float GetVerticalFOV(this CvsCameraInfo info); // degrees
public static float GetHorizontalFOV(this CvsCameraInfo info);// degrees
Derive the usable camera matrices and field-of-view from a CvsCameraInfo. GetExtrinsic returns the camera's world pose with handedness already corrected for Unity; the FOV accessors return degrees.
Core ↔ Unity conversion
// Core → Unity (positions in meters)
public static Vector3 ToUnity(this AR51.Mocap.Filters.Double3 v); // meters, double→float
public static Color ToUnity(this Core.Color color);
public static Vector2 ToUnity(this Core.Vector2 v);
public static Vector3 ToUnity(this Core.Vector3 v);
public static Quaternion ToUnity(this Core.Quaternion v);
public static Bounds ToUnity(this Bound2D bounds);
// Unity → Core
public static Core.Color ToCore(this Color c);
public static Core.Vector2 ToCore(this Vector2 v);
public static Core.Vector3 ToCore(this Vector3 v);
public static Core.Vector4 ToCore(this Vector4 v);
public static Core.Quaternion ToCore(this Quaternion q);
// Color helpers
public static Color Parse(this Color _, string colorName); // named CSS-ish colors → Color (Color.clear if unknown)
public static Color FromUInt(this Color _, uint hex); // 0xAARRGGBB → Color
Convert between AR 51 Core math types and Unity types. Positions are in meters on both sides — no rescaling is applied. Parse maps a named color (returning Color.clear if the name is unknown); FromUInt builds a color from a packed 0xAARRGGBB value.
// Core mocap position → Unity world-space (meters)
Vector3 wrist = coreWrist.ToUnity();
// Packed hex → Color
Color accent = default(Color).FromUInt(0xFF33AAFF); // ARGB
Log / LogWarning / LogError
public static void Log(this object sender, string msg, /* [Caller*] */ ...);
public static void LogWarning(this object sender, string msg, ...);
public static void LogError(this object sender, string msg, ...);
public static void Log(this MonoBehaviour sender, string msg, ...);
Context-aware logging extensions. They auto-prefix each message with File.Method[line] (captured via [Caller*] attributes) — prefer them over hand-written context strings. Available on any object (and a MonoBehaviour overload).
this.Log("connected"); // → "MyBehaviour.Start[42] connected"
this.LogError("stream dropped");
ObjectFieldExtensions
static classpublic static class ObjectFieldExtensions
Namespace: AR51.Unity.SDK
Reflection get/set of a field or property by name. Includes non-public members by default (DefaultFlags = BindingFlags.NonPublic | BindingFlags.Public).
public const BindingFlags DefaultFlags = BindingFlags.NonPublic | BindingFlags.Public;
public static T GetValue<T>(this object owner, string fieldName, BindingFlags flags = DefaultFlags);
public static void SetValue(this object owner, string fieldName, object value, BindingFlags flags = DefaultFlags);
⚠️ GetValue returns default(T) if the member isn't found (no exception); SetValue logs a warning on failure. Reflection-based access is for advanced/interop scenarios — prefer the typed API where one exists.
// Read a private field by name
float smoothing = consumer.GetValue<float>("_smoothingFactor");
consumer.SetValue("_smoothingFactor", 0.9f);
TextureExtensions
static classpublic static class TextureExtensions
Namespace: AR51.Unity.SDK
GPU-assisted texture resampling and JPG encoding.
public static Texture2D Resample(this Texture source, int width, int height,
TextureFormat textureFormat = TextureFormat.RGBA32, bool mipChain = true, bool linear = false);
public static Texture2D ResampleTo(this Texture source, Texture2D target, RenderTexture renderTexture = null);
public static byte[] EncodeToJPG(this Texture source, ref Texture2D target, int width, int height, int quality = 70);
width/height are in pixels; quality is 0–100 (default 70). Resample returns a new Texture2D; ResampleTo blits into an existing target. EncodeToJPG resizes (clamped to the source dimensions) into target and returns the JPG bytes.
// Resize a camera frame and encode at quality 85
Texture2D thumb = null;
byte[] jpg = cameraFrame.EncodeToJPG(ref thumb, 640, 360, quality: 85);
AnimationTimer
classpublic class AnimationTimer
Namespace: AR51.Unity.SDK
A lightweight fixed-duration timer driven by Time.time. Construct it with a duration in seconds, then poll Factor/SmoothFactor each frame to drive an animation.
| Member | Type | Description |
|---|---|---|
StartTime | float | capture time when the timer was created (seconds), read-only |
Duration | float | configured duration in seconds, read-only |
ElapsedTime | float | seconds since StartTime |
Factor | float | linear progress, 0–1 |
SmoothFactor | float | smoothstep progress, 0–1 |
IsRunning | bool | true while ElapsedTime < Duration |
public AnimationTimer(float duration); // duration in seconds
var fade = new AnimationTimer(0.5f); // half-second fade
// ...each frame:
material.color = Color.Lerp(from, to, fade.SmoothFactor);
if (!fade.IsRunning) { /* done */ }
BiDictionary<T1,T2>
BiDictionary<T1,T2> global namespacepublic class BiDictionary<T1, T2> : IDictionary<T1, T2>
Namespace: global (no namespace)
A bidirectional dictionary: look up by key in either direction. Implements IDictionary<T1,T2> plus mirrored overloads keyed by T2. Both the key and the value must be unique — each side is a real dictionary.
public T2 this[T1 key] { get; set; }
public T1 this[T2 key] { get; set; }
public void Add(T1 key, T2 value); // (+ T2 / KeyValuePair overloads, both directions)
public bool ContainsKey(T1 key); public bool ContainsKey(T2 key);
public bool TryGetValue(T1 key, out T2 value); public bool TryGetValue(T2 key, out T1 value);
public bool Remove(T1 key); public bool Remove(T2 key);
public ICollection<T1> Keys { get; } public ICollection<T2> Values { get; }
public int Count { get; } public bool IsReadOnly { get; }
public void Clear();
⚠️ Because both sides are unique dictionaries, T1 and T2 should be distinct types — otherwise the overloads keyed by T1 vs T2 are ambiguous to the compiler.
var map = new BiDictionary<string, int>();
map.Add("alice", 1);
int id = map["alice"]; // forward
string n = map[1]; // reverse
See also
SkeletonConsumer— usesIsIdentifiedinternally forIgnoreUnidentifiedCameraFeedClient— owns theCvsCameraInfothe camera accessors read fromServiceManager— resolves theComponentDescriptorwhose endpointGetEndpointformats- Recording & playback — keyframe utilities in the same area
- Class index — all Unity SDK types