# UAnchorServiceComponent

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

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

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

Hosts the **spatial-anchor / guardian-boundary** service. Drop one on the SDK actor to get world-locked anchors and guardian boundaries: it manages the spawned anchor actors and boundary geometry in the level, fires Blueprint events on anchor lifecycle, and can compensate anchor transforms when device tracking is lost. Acts as a singleton.

Anchor and boundary creation, deletion, visibility, and guardian management are driven **remotely over the service** (server-side handlers), not by Blueprint calls. The caller-facing surface is: bind the events, read the anchors/transform, and convert coordinates.

:::caution[Units & space]
Unreal world units are **centimeters** and rotations are **degrees**; AR 51 mocap/CVS data is in **meters** (and a different coordinate convention). Anchor transforms returned here are in **UE world space (cm/deg)**. Any position/rotation crossing the AR 51 ↔ Unreal boundary must be converted — use the [coordinate-conversion helpers](#ar51sdktoworldspace--worldtoar51sdkspace).
:::

## Properties

All `EditAnywhere, BlueprintReadWrite`.

<div className="apiPropTable">

| Property | Type | Default | Description |
|---|---|---|---|
| **General** | | | |
| `IsAutoSyncCameraToAnchor` | `bool` | `true` | keep the camera aligned to the active anchor automatically |
| `AnchorBP` | [`TSubclassOf<AActor>`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor) | — | Blueprint spawned to visualize each anchor |
| `BoundaryBP` | [`TSubclassOf<AActor>`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor) | — | Blueprint used for boundary geometry |
| `BoundaryMaterial` | `TSubclassOf<UMaterial>` | — | material applied to boundary meshes |
| `BoundaryHeight` | `float` | `100` | extruded boundary wall height — **cm** ⚠️ unit inferred |
| **Tracking-lost compensation** | | | |
| `IsTrackingLostCompensate` | `bool` | `false` | enable tracking-loss compensation |
| `TrackingLostCompensateThreshold` | `float` | `50` | distance jump that triggers compensation — ⚠️ likely **cm** |
| `TrackingLostZeroPositionsCooldownTimeout` | `float` | `0.2` | seconds |
| `TrackingLostDeltaTimeThreshold` | `float` | `~0.032` | seconds (2×16 ms) |
| `TrackingLostMaxXYDegreesCompensate` | `float` | `5` | clamp on rotational compensation — **degrees** |
| **Debug** | | | |
| `IsPrintAnchorLocation` | `bool` | `true` | log anchor world locations |

</div>

## Method summary

**Static**

| Method | Returns | |
|---|---|---|
| [`GetAnchorServiceSingleton`](#getanchorservicesingleton) | `UAnchorServiceComponent*` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`GetAnchorTransform`](#getanchortransform) | `FTransform` | <Badge tone="accent">BlueprintCallable</Badge> |
| [`AR51SDKToWorldSpace` / `WorldToAR51SDKSpace`](#ar51sdktoworldspace--worldtoar51sdkspace) | `void` | <Badge tone="accent">BlueprintCallable</Badge> · overloads |

**Instance**

| Method | Returns | |
|---|---|---|
| [`GetAnchors`](#getanchors) | [`TArray<AActor*>`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor) | <Badge>C++ only</Badge> |
| [`GetAnchorById`](#getanchorbyid) | [`AActor*`](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor) | <Badge>C++ only</Badge> |

## Events

`UPROPERTY(BlueprintAssignable)`, dynamic multicast. Bind in C++ with `AddDynamic`, or as a red event node in Blueprint.

| Event | Signature | Fires when |
|---|---|---|
| `OnAnchorCreated` | `FOnAnchorCreated(FString AnchorId)` | an anchor is created |
| `OnAnchorDestroyed` | `FOnAnchorDestroyed(FString AnchorId)` | an anchor is destroyed |
| `OnTrackingLostCompensated` | `FTrackingLostCompensationEvent()` | the SDK detects tracking loss and re-aligns the anchor — a good hook for UI/logging |

## Method details

### GetAnchorServiceSingleton

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

```cpp
static UAnchorServiceComponent* GetAnchorServiceSingleton();
```

The live anchor-service instance — the usual way to reach it from anywhere.

<Returns type="UAnchorServiceComponent*">the singleton, or `nullptr` if none is in the level</Returns>

<Example inferred>

```cpp
void AMyAnchorManager::BeginPlay()
{
    Super::BeginPlay();
    if (auto* Anchors = UAnchorServiceComponent::GetAnchorServiceSingleton())
    {
        Anchors->OnAnchorCreated.AddDynamic(this, &AMyAnchorManager::HandleAnchorCreated);
        Anchors->OnAnchorDestroyed.AddDynamic(this, &AMyAnchorManager::HandleAnchorDestroyed);
    }
}
```

</Example>

</ApiBody>

### GetAnchors

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

```cpp
const TArray<AActor*> GetAnchors() const;
```

All live anchor actors currently spawned in the level. Not a `UFUNCTION` — C++ only.

<Returns type="TArray<AActor*>" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor">every spawned anchor actor</Returns>

</ApiBody>

### GetAnchorById

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

```cpp
AActor* GetAnchorById(const FString& id) const;   // also a const std::string& overload
```

Look up a spawned anchor actor by its id. Not a `UFUNCTION` — C++ only.

<Params>
<Param name="id" type="FString">the anchor id (as delivered by `OnAnchorCreated`)</Param>
</Params>

<Returns type="AActor*" typeHref="https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor">the anchor actor, or `nullptr` if no anchor with that id exists</Returns>

<Example inferred>

```cpp
void AMyAnchorManager::HandleAnchorCreated(FString AnchorId)
{
    auto* Anchors = UAnchorServiceComponent::GetAnchorServiceSingleton();
    if (AActor* Anchor = Anchors->GetAnchorById(AnchorId))
        SpawnContentAt(Anchor->GetActorTransform());   // UE world space, cm/deg
}
```

</Example>

</ApiBody>

### GetAnchorTransform

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

```cpp
static FTransform GetAnchorTransform();
```

The current **active-anchor** transform, in Unreal world space (cm / degrees). Use it to position content relative to the anchor.

<Returns type="FTransform">the active anchor's world transform — **UE world space, cm/deg**</Returns>

</ApiBody>

### AR51SDKToWorldSpace / WorldToAR51SDKSpace

<ApiBody kind="method" tags="static, BlueprintCallable, overloads">

```cpp
// AR 51 (meters) → Unreal world (cm), in place
static void AR51SDKToWorldSpace(FVector& position);
static void AR51SDKToWorldInplace(TArray<FVector>& positions);
static void AR51SDKToWorldSpace(FQuat& rotation);

// Unreal world (cm) → AR 51 (meters), in place
static void WorldToAR51SDKSpace(FVector& position);
static void WorldToAR51SDKSpace(TArray<FVector>& positions);
static void WorldToAR51SDKSpace(FQuat& rotation);
static void WorldToAR51SDKSpace(TArray<FQuat>& rotations);
```

The bridge between **AR 51 space (meters)** and **Unreal world space (cm)** — these convert position and rotation *in place* (the argument is modified). AR 51 uses both a different unit (meters vs cm) and a different coordinate convention, so a raw value cannot be used across the boundary unconverted. Call `AR51SDKToWorldSpace` on anything coming **from** the AR 51 system before using it in the level; call `WorldToAR51SDKSpace` on anything you send **to** the AR 51 system.

<Params>
<Param name="position" type="FVector">a position to convert in place — read as **cm** after `AR51SDKToWorldSpace`, as **meters** after `WorldToAR51SDKSpace`</Param>
<Param name="rotation" type="FQuat">a rotation to convert in place (coordinate convention is remapped, not just scaled)</Param>
</Params>

<Example inferred>

```cpp
// A point reported by the AR 51 system, in meters → use it in the UE level (cm)
FVector P = AnchorPointFromAR51();                 // AR 51 space, meters
UAnchorServiceComponent::AR51SDKToWorldSpace(P);   // now UE world space, cm
MyActor->SetActorLocation(P);

// Send a UE world-space position back to the AR 51 system
FVector Q = MyActor->GetActorLocation();           // UE world space, cm
UAnchorServiceComponent::WorldToAR51SDKSpace(Q);   // now AR 51 space, meters
```

</Example>

</ApiBody>

## See also

- [`UWorldAnchorConstraintComponent`](/docs/sdk-api/unreal-api/hands-boundary-anchors#uworldanchorconstraintcomponent) — pins a scene component to the active anchor each tick using `GetAnchorTransform()`
- [`AAR51SDK`](/docs/sdk-api/unreal-api/classes/aar51sdk) — the connection root actor that hosts this service
- [`ISingleton<T>`](/docs/sdk-api/unreal-api/utilities-platform#isingletont) — the singleton base providing the `Get…Singleton()` accessor
- [Class index](/docs/sdk-api/unreal-api/classes) — all Unreal SDK types
