# ObjectDetectionConsumer

<Badge tone="type">class · Singleton&lt;ObjectDetectionConsumer&gt;</Badge> <Badge>Unity component</Badge> <Badge>singleton</Badge>

```csharp
public class ObjectDetectionConsumer : Singleton<ObjectDetectionConsumer>
```

**Namespace:** `AR51.Unity.SDK` · **Inherits:** `Singleton<ObjectDetectionConsumer>` (MonoBehaviour) — access the live scene instance through `ObjectDetectionConsumer.Instance`.

Subscribes to the object-detection stream and spawns/updates GameObjects for detected markers and 6-DoF tracked objects. Each spawned GameObject carries a [`TrackedInstance`](/docs/sdk-api/unity-api/object-detection#trackedinstance) component describing its current state. Positions are in Unity world space (**meters**), transformed through the configured `Origin`/anchor.

:::caution[Units]
Unity positions, radii, and lengths are in **meters** (world space); rotations are `Quaternion`; angles in **degrees**. Several fields below carry ⚠️ flags where the source unit or behavior needs confirmation — preserved verbatim.
:::

## Properties

All Inspector configuration fields are `public` (set in the Inspector or before `Start`). Read-only state is exposed as get-only properties.

<div className="apiPropTable">

| Property | Type | Default | Description |
|---|---|---|---|
| **Display toggles** | | | |
| `ShowMarkers` | `bool` | `true` | show plain detection markers |
| `ShowObjects` | `bool` | `true` | show 6-DoF tracked objects |
| `ShowSkeletonMarkers` | `bool` | `false` | show skeleton joint markers |
| `ShowMarkerItems` | `bool` | `true` | show prefab marker-items in place of markers |
| **Prefabs & materials** | | | |
| `MarkerMaterial` | `Material` | — | base material for spawned markers / default cubes |
| `Prefabs` | `GameObject[]` | — | prefab pool for 6-DoF objects, matched by name to the server object `Name` |
| `MarkerItems` | [`MarkerItem[]`](#markeritem) | — | per-marker-type prefab overrides |
| **Marker sizing** | | | |
| `MarkerSize` | `float` | `1` | global scale multiplier for markers (applied as `MarkerSize * Radius`) |
| `BasketballRadius` | `float` | `0.12` | fixed radius (m) for markers whose type contains `"ball"` |
| `SkeletonMarkerSize` | `float` | `0.05` | scale (m) for skeleton markers |
| `SkeletonMarkerColor` | `Color` | `Color.blue` | color applied to skeleton markers |
| **Non-max suppression** | | | |
| `EnableNMSWorkAround` | `bool` | `false` | hide duplicate new markers near existing ones |
| `NMSThreshold` | `float` | `0.01` | distance (m) under which a new marker is suppressed as a duplicate |
| **Kalman filtering** | | | |
| `EnabledFiltering` | `bool` | `false` | enable Kalman filtering of marker/object positions |
| `ProcessNoise` | `double` | `2` | Kalman process-noise parameter |
| `MeasurementNoise` | `double` | `0.005` | Kalman measurement-noise parameter |
| `FutureDeltaTime` | `double` | `1.0/120.0` | prediction horizon (seconds) |
| `UseDiscreteWhiteNoise` | `bool` | `true` | Kalman noise-model toggle |
| `UseAcceleration` | `bool` | `true` | include an acceleration term in the filter model |
| **Smoothing (6-DoF objects)** | | | |
| `SmoothRotationFactor` | `float` | `0.2` | `[0..1]` slerp weight for object rotation smoothing |
| `SmoothPositionalFactor` | `float` | `0.2` | `[0..1]` lerp weight for object position smoothing |
| `SmoothRotationAngleThreshold` | `float` | `12` | `[0..90]` degrees; above this, rotation snaps instead of smoothing |
| `SmoothPositionalThreshold` | `float` | `0.03` | distance (m) above which position snaps instead of smoothing |
| **Placement & misc** | | | |
| `ModelLayer` | `int` | `0` | Unity layer assigned to spawned objects |
| `Origin` | `Transform` | — | origin transform; spawned content aligns to its local-to-world |
| `IsDebug` | `bool` | `false` | debug flag |
| **Read-only state** | | | |
| `ModelLayerName` | `string` | — | name of `ModelLayer` *(get-only)* |
| `CameraIds` | `List<string>` | — | IDs of cameras contributing to the latest frame; refreshed each frame *(get-only)* |
| `TrackedInstances` | [`IEnumerable<TrackedInstance>`](/docs/sdk-api/unity-api/object-detection#trackedinstance) | — | all currently tracked instances (markers + objects) *(get-only)* |
| `TrackedMarkers` | [`IEnumerable<TrackedInstance>`](/docs/sdk-api/unity-api/object-detection#trackedinstance) | — | currently tracked markers only *(get-only)* |
| `TrackedObjects` | [`IEnumerable<TrackedInstance>`](/docs/sdk-api/unity-api/object-detection#trackedinstance) | — | currently tracked 6-DoF objects only *(get-only)* |

</div>

## Method summary

**Instance**

| Method | Returns | |
|---|---|---|
| [`OnObjectDetected`](#onobjectdetected) | `void` | <Badge tone="accent">stream callback</Badge> |
| [`AddTrackedObject`](#addtrackedobject) | `void` | <Badge tone="accent">public</Badge> |
| [`RemoveTrackedObject`](#removetrackedobject) | `void` | <Badge tone="accent">public</Badge> |
| [`ResetModels`](#resetmodels) | `void` | <Badge tone="accent">public</Badge> |

→ Full descriptions in [Method details](#method-details) below.

## Events

Standard C# `event` delegates — subscribe with `+=`.

| Event | Signature | Fires when |
|---|---|---|
| `OnObjectDetectionReceived` | `EventHandler<ObjectDetectionReply>` | once per received detection frame, at the **start** of processing, before GameObjects are updated |

The `ObjectDetectionReply` argument (⚠️ declared elsewhere — `AR51.GRPC.CVS` transport type) carries the frame's markers, items, cameras, and capture time. Use it to observe raw detection frames as they arrive.

## Method details

### OnObjectDetected

<ApiBody kind="method" tags="public">

```csharp
public void OnObjectDetected(ObjectDetectionReply e);
```

Processes one detection frame: fires `OnObjectDetectionReceived`, then creates / updates / positions the marker and object GameObjects. Normally invoked internally from the stream; call it to feed a frame manually (e.g. playback). ⚠️ `ObjectDetectionReply` is a transport type declared elsewhere.

<Params>
<Param name="e" type="ObjectDetectionReply">the detection frame to process</Param>
</Params>

</ApiBody>

### AddTrackedObject

<ApiBody kind="method" tags="public">

```csharp
public void AddTrackedObject(string name, TrackedInstance[] markers);
```

Registers a new trackable rigid object on the server, defined by the given marker instances (their color types and positions, recentered to their average). No-op with an error log if the object-detection client is unavailable.

<Params>
<Param name="name" type="string">name to register the new tracked object under</Param>
<Param name="markers" type="TrackedInstance[]">the marker instances that define the rigid body (positions in meters, recentered to their average)</Param>
</Params>

<Example inferred>

```csharp
// Define a rigid object from the currently-tracked markers
var consumer = ObjectDetectionConsumer.Instance;
consumer.AddTrackedObject("Racket", consumer.TrackedMarkers.ToArray());
```

</Example>

</ApiBody>

### RemoveTrackedObject

<ApiBody kind="method" tags="public">

```csharp
public void RemoveTrackedObject(string name);
```

Unregisters a previously added tracked object by name.

<Params>
<Param name="name" type="string">the name passed to `AddTrackedObject`</Param>
</Params>

</ApiBody>

### ResetModels

<ApiBody kind="method" tags="public">

```csharp
public void ResetModels();
```

Destroys all spawned marker / object GameObjects and clears internal tracking. Call to flush stale visuals (e.g. on scene reset or anchor change).

</ApiBody>

## Inspector configuration

Drop the component on a GameObject (or reach it via `ObjectDetectionConsumer.Instance`). The fields under [Properties](#properties) are the Inspector knobs:

- **Display toggles** (`ShowMarkers`, `ShowObjects`, `ShowSkeletonMarkers`, `ShowMarkerItems`) gate which detection categories are rendered.
- **`Prefabs`** is the pool for 6-DoF objects, matched by name to the server object `Name`; **`MarkerItems`** override individual marker types with custom prefabs (see [`MarkerItem`](#markeritem)).
- **`Origin`** anchors all spawned content — set it to the transform that represents your tracking space.
- **Filtering / smoothing** fields tune the Kalman filter and per-object position/rotation smoothing.

---

## InstanceType

<Badge tone="type">enum</Badge>

```csharp
public enum InstanceType { Marker, Object }
```

**Namespace:** `AR51.Unity.SDK`. Nested in `ObjectDetectionConsumer`. Classifies a [`TrackedInstance`](/docs/sdk-api/unity-api/object-detection#trackedinstance).

| Value | Meaning |
|---|---|
| `Marker` | a simple marker — sphere / 3-DoF point |
| `Object` | a full 6-DoF tracked object |

---

## MarkerItem

<Badge tone="type">class · [Serializable]</Badge>

```csharp
[Serializable]
public class MarkerItem
```

**Namespace:** `AR51.Unity.SDK`. Nested in `ObjectDetectionConsumer`. Maps a marker type string to a prefab to spawn in place of the default marker. Edit entries in the Inspector via the `MarkerItems` array.

<div className="apiPropTable">

| Field | Type | Default | Description |
|---|---|---|---|
| `MarkerType` | `string` | — | the marker type / color label this entry matches |
| `Prefab` | `GameObject` | — | prefab instantiated and tracked at the marker's position |
| `Enabled` | `bool` | `true` | whether this marker-item is shown |

</div>

---

## TrackedMarkerExtensions

<Badge tone="type">static class</Badge>

```csharp
public static class TrackedMarkerExtensions
```

**Namespace:** `AR51.Unity.SDK`. Static (non-MonoBehaviour) utility extension methods on `TrackedMarker` for interpreting marker IDs.

### IsSkeletonMarker

<ApiBody kind="method" tags="static, extension">

```csharp
public static bool IsSkeletonMarker(this TrackedMarker marker);
```

Tests whether the marker represents a skeleton joint (its `Id` contains `"Skeleton"`), letting callers distinguish skeleton-driven markers from free-standing detection markers.

<Returns type="bool">`true` if the marker is a skeleton joint marker</Returns>

</ApiBody>

### TrySkeletonMarkerInfo

<ApiBody kind="method" tags="static, extension">

```csharp
public static bool TrySkeletonMarkerInfo(this TrackedMarker marker, out string skeletonId, out string jointName);
```

Attempts to parse a skeleton marker's `Id` into a skeleton identifier and joint name. Returns `false` (with `null` outs) for non-skeleton markers. On success, `skeletonId` is normalized to a `"Skeleton:Classic..."` form and `jointName` is the joint label. ⚠️ needs confirmation: the exact `skeletonId` / `jointName` string formats depend on the server's marker-ID naming scheme.

<Params>
<Param name="marker" type="TrackedMarker">the marker to parse</Param>
<Param name="skeletonId" type="out string">on success, the normalized skeleton identifier; `null` otherwise</Param>
<Param name="jointName" type="out string">on success, the joint label; `null` otherwise</Param>
</Params>

<Returns type="bool">`true` if the marker is a skeleton marker and was parsed</Returns>

</ApiBody>

## See also

- [`TrackedInstance`](/docs/sdk-api/unity-api/object-detection#trackedinstance) — the per-instance data model attached to each spawned marker / object GameObject
- [`ObjectTransformConsumer`](/docs/sdk-api/unity-api/classes/objecttransformconsumer) — the parallel consumer for generic object transforms (position / rotation / scale)
- [`ObjectTransform`](/docs/sdk-api/unity-api/classes/objecttransform) — a single object's pose fed to `ObjectTransformConsumer`
- [`XRHeadsetTracker`](/docs/sdk-api/unity-api/classes/xrheadsettracker) — streams XR-device transforms into `ObjectTransformConsumer`
- [`ServiceManager`](/docs/sdk-api/unity-api/classes/servicemanager) — the connection entry-point that must be running before detections arrive
- [Class index](/docs/sdk-api/unity-api/classes) — all Unity SDK types
