# UObjectDetectionConsumer

<Badge tone="type">UCLASS · UActorComponent</Badge> <Badge>BlueprintSpawnableComponent</Badge> <Badge>singleton</Badge>

```cpp
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class AR51SDK_API UObjectDetectionConsumer : public UActorComponent, public ISingleton<UObjectDetectionConsumer>
```

**Inherits:** [`UActorComponent`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UActorComponent) *(Unreal Engine)* · [`ISingleton<UObjectDetectionConsumer>`](/docs/sdk-api/unreal-api/utilities-platform#isingletont)

Drop one on an actor in the level. On `BeginPlay` it registers with the AR 51 SDK, auto-connects when the CVS component appears on the network, and from then on spawns, updates, and prunes a child actor for every detected **marker** (a colored ball/disc tracker) and **object** (a full 6-DoF tracked prop). The owning actor's transform is the parent/anchor space for everything it spawns.

You configure it in the editor (meshes, materials, prefabs, smoothing, pruning) and then read live state by polling — there are no detection events. Acts as a C++ singleton.

:::caution[Units]
The AR 51 system reports positions in **meters**; this component converts them to Unreal **centimeters** internally before placing spawned actors, so all spawned actor transforms are in UE world units (cm). A few fields are **not** converted and stay in **AR 51 meters** — notably [`UTrackedInstance::Radius`](/docs/sdk-api/unreal-api/object-detection#utrackedinstance) and the smoothing thresholds below; each is flagged inline.
:::

:::tip[How-to]
This page is **reference** (facts only). For the step-by-step *drop the component → read tracked markers/objects* walkthrough, see the [How-to guide](/docs/sdk-api/unreal-api/object-detection).
:::

## Properties

All `EditAnywhere, BlueprintReadWrite`, grouped by editor category.

<div className="apiPropTable">

| Property | Type | Default | Description |
|---|---|---|---|
| **General** | | | |
| `MarkerMaterial` | [`UMaterialInterface*`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UMaterialInterface) | — | base material for marker spheres; a dynamic instance is created per marker and tinted from `ColorName` (sets vector param `"Color"`). Logs an error at `BeginPlay` if null |
| `MarkerMesh` | [`UStaticMesh*`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UStaticMesh) | — | mesh used for the sphere spawned per marker. Logs an error at `BeginPlay` if null |
| `MarkerScale` | `float` | `1.0` | multiplier on marker size; final scale = `MarkerScale * radius` (uniform) |
| `DefaultObjectMesh` | [`UStaticMesh*`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/UStaticMesh) | — | fallback mesh for a detected **object** when no matching prefab is found in `Prefabs` (spawned as a small cube, ~0.2 relative scale) |
| `ShowMarkers` | `bool` | `true` | toggles visibility of all marker actors |
| `Prefabs` | `TArray<TSubclassOf<AActor>>` | — | candidate Blueprints for 6-DoF objects; matched by the object's `name` (or `name + "_C"`) against the class name |
| `SmoothRotation` | `float` | `0` | lerp factor for the rolling-ball rotation applied to the **owner** actor each tick (`0` = none). ⚠️ unusual owner-rotation behavior — see [Lifecycle](#lifecycle) |
| **Inactives** | | | |
| `DestroyInactives` | `bool` | `true` | master switch for the hide/destroy pruning pass each tick |
| `HideMarkerMaxSeconds` | `float` | `0.02` | seconds without an update before an instance's actor is hidden. ⚠️ very small (~1 frame at 50 fps) — markers flicker hidden between updates by design |
| `InactivesMaxSeconds` | `float` | `2.0` | seconds without an update before an instance's actor (and any `AttachedItem`) is destroyed and removed from tracking |
| **MarkerItems** | | | |
| `MarkerItems` | [`TArray<FMarkerItem>`](#fmarkeritem) | — | rules for spawning extra visuals on markers by type (see [FMarkerItem](#fmarkeritem)) |
| `ShowMarkerItems` | `bool` | `true` | toggles visibility of the spawned `AttachedItem` actors |
| **Smoothing** *(object 6-DoF only)* | | | |
| `SmoothPositionalFactor` | `float` | `0.2` | lerp blend when an object's position delta is small; higher = stickier/slower |
| `SmoothPositionalThreshold` | `float` | `0.03` | if the new position is within this distance of the current, smooth (lerp); otherwise snap. ⚠️ Units: compared against a UE-space delta (cm), but `0.03` looks like a **meters** threshold — unclear/unverified |
| `SmoothRotationFactor` | `float` | `0.2` | lerp blend for yaw when within threshold |
| `SmoothRotationAngleThreshold` | `float` | `12.0` | **degrees**; if yaw change is below this, smooth-rotate, otherwise snap to the new orientation |

</div>

## Method summary

All query methods below are **C++ only** — they are not marked `UFUNCTION`, so they are **not callable from Blueprint** as written.

**Instance**

| Method | Returns | |
|---|---|---|
| `IsConnected` | `bool` | <Badge>C++ only</Badge> |
| `GetTrackedMarkers` | [`TArray<UTrackedInstance*>`](/docs/sdk-api/unreal-api/classes/utrackedinstance) | <Badge>C++ only</Badge> |
| `GetTrackedObjects` | [`TArray<UTrackedInstance*>`](/docs/sdk-api/unreal-api/classes/utrackedinstance) | <Badge>C++ only</Badge> |

:::caution[⚠️ unverified — Blueprint access]
`IsConnected`, `GetTrackedMarkers`, and `GetTrackedObjects` are the natural query API but are **not** `UFUNCTION(BlueprintCallable)`, so today they are reachable only from C++. If Blueprint access is intended, they would need the `UFUNCTION` markup added.
:::

→ Full descriptions in [Method details](#method-details) below. Connection itself is handled automatically (see [Lifecycle](#lifecycle)); there is no public `Connect`/`Disconnect`.

## Events

**None.** This consumer is **poll-only** — there are no `BlueprintAssignable` delegates or dynamic-multicast events for "object detected / updated / removed." Detection runs entirely inside a private callback that spawns, updates, and (via the prune pass) destroys actors directly. Observe state by polling [`GetTrackedMarkers`](#gettrackedmarkers) / [`GetTrackedObjects`](#gettrackedobjects), or by watching the spawned child actors.

:::caution[⚠️ unverified — no notification surface]
If game code needs "on detected / updated / removed" callbacks, that surface does not currently exist and would have to be added (e.g. `BlueprintAssignable` `FObjectDetected` / `FObjectUpdated` / `FObjectRemoved` delegates).
:::

## Method details

### IsConnected

<ApiBody kind="method" tags="C++ only">

```cpp
bool IsConnected();
```

`true` while the component is connected to a CVS endpoint.

<Returns type="bool">whether the live feed is connected</Returns>

</ApiBody>

### GetTrackedMarkers

<ApiBody kind="method" tags="C++ only">

```cpp
TArray<UTrackedInstance*> GetTrackedMarkers() const;
```

Snapshot of all currently-tracked instances of type `Marker` (point/sphere trackers — id + color + radius, position only).

<Returns type="TArray<UTrackedInstance*>" typeHref="/docs/sdk-api/unreal-api/classes/utrackedinstance">the tracked markers this frame</Returns>

<Example inferred>

```cpp
auto* OD = UObjectDetectionConsumer::GetSingleton();
if (OD && OD->IsConnected())
{
    for (UTrackedInstance* M : OD->GetTrackedMarkers())   // C++ only
    {
        const FVector Loc = M->GetOwner()->GetActorLocation();   // UE cm
        UE_LOG(LogTemp, Log, TEXT("%s %s @ %s"), *M->ColorName, *M->Id, *Loc.ToString());
    }
}
```

</Example>

</ApiBody>

### GetTrackedObjects

<ApiBody kind="method" tags="C++ only">

```cpp
TArray<UTrackedInstance*> GetTrackedObjects() const;
```

Snapshot of all currently-tracked instances of type `Object` (full 6-DoF props matched to a `Prefabs` Blueprint).

<Returns type="TArray<UTrackedInstance*>" typeHref="/docs/sdk-api/unreal-api/classes/utrackedinstance">the tracked objects this frame</Returns>

</ApiBody>

## Lifecycle

This consumer manages its own connection and spawning — you configure it and read it, you do not drive it.

- **BeginPlay** registers with the AR 51 SDK registration service and subscribes to component add/remove. It auto-connects when a CVS endpoint appears on the network and auto-disconnects when it is removed. Logs errors if `MarkerMesh` or `MarkerMaterial` are unset.
- **On each detection frame**, markers spawn a sphere (`MarkerMesh`, tinted from `ColorName`) parented under the owner; objects spawn the matching `Prefabs` entry or a `DefaultObjectMesh` cube. Existing instances (keyed by `Id`) are updated in place — position is unit-converted to cm; objects also get smoothed yaw/position per the **Smoothing** properties.
- **TickComponent** runs the prune pass (hide after `HideMarkerMaxSeconds`, destroy after `InactivesMaxSeconds`, gated by `DestroyInactives`) and additionally applies a "rolling ball" world-rotation to the **owner** actor based on how far it moved this frame.

:::caution[⚠️ unverified — owner rolling-rotation]
The per-tick rolling-ball rotation applied to the **owner** actor (driven by `SmoothRotation`) is unusual for a tracking consumer. Confirm whether it is intended public behavior or a leftover before relying on it.
:::

## FMarkerItem

<Badge tone="type">USTRUCT(BlueprintType)</Badge>

```cpp
USTRUCT(BlueprintType)
struct FMarkerItem
```

An editor-configured rule: "when a marker of this type is detected, also spawn this Blueprint as a visual." Populate the consumer's `MarkerItems` array with these. On a match, the spawned actor is parented to the marker and stored as its [`UTrackedInstance::AttachedItem`](/docs/sdk-api/unreal-api/classes/utrackedinstance); it is destroyed with the marker.

<div className="apiPropTable">

| Field | Type | Default | Description |
|---|---|---|---|
| `MarkerType` | `FString` | — | substring matched (case-sensitive `Contains`) against a marker's `ColorName`; a match triggers spawning `Blueprint` |
| `Blueprint` | `TSubclassOf<AActor>` | — | actor class spawned and parented to the matched marker; stored as the marker's `AttachedItem` |
| `bEnabled` | `bool` | `true` | if `false`, this rule is skipped |

</div>

All fields are `EditAnywhere, BlueprintReadWrite`.

## See also

- [`UTrackedInstance`](/docs/sdk-api/unreal-api/classes/utrackedinstance) — the per-detection data record returned by the query methods
- [`EInstanceType`](/docs/sdk-api/unreal-api/object-detection#einstancetype) — discriminates a tracked instance as a `Marker` or `Object`
- [Object Detection area](/docs/sdk-api/unreal-api/object-detection) — overview, data model, and units for marker/object tracking
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
