# Scene components & anchors

<Badge tone="type">scene components</Badge> <Badge>Unity component</Badge>

A cluster of small `MonoBehaviour`s you drop on scene GameObjects to visualize spatial anchors and the play-area boundary, constrain a transform, billboard toward the camera, or feed Inspector-assigned hand transforms into the SDK as an adapter.

:::caution[Units]
This is a Unity SDK page — all positions, lengths, and heights are in **Unity world-space meters**; rotations are [`Quaternion`](https://docs.unity3d.com/ScriptReference/Quaternion.html); angles are in **degrees**.
:::

Five components live here:

| Component | Namespace | Role |
|---|---|---|
| [`AnchorVisualization`](#anchorvisualization) | `AR51.Unity.SDK` | save/disable UI control for a visual spatial anchor |
| [`BoundaryVisualization`](#boundaryvisualization) | `AR51.Unity.SDK` | builds a wall mesh + outline for a recorded play-area boundary |
| [`ConstrainPosition`](#constrainposition) | `AR51.Unity.SDK.Components` | copies a source transform's position each frame |
| [`CustomHandsAdapter`](#customhandsadapter) | `AR51.Unity.SDK.Components` | in-scene [`IHandsAdapter`](/docs/sdk-api/unity-api/classes/adapters) driven by Inspector transforms |
| [`FaceCamera`](#facecamera) | `AR51.Unity.SDK.Components` | yaw-billboards this GameObject toward the camera |

## AnchorVisualization

<Badge tone="type">class · MonoBehaviour</Badge> <Badge>Unity component</Badge>

```csharp
public class AnchorVisualization : MonoBehaviour
```

**Namespace:** `AR51.Unity.SDK`

A localized UI/control entry for an AR 51 visual spatial anchor. Attach it to a GameObject; it exposes save/disable requests both as code events and as an Inspector-wireable `UnityEvent`, so anchor UI (buttons, gestures) can drive persistence without your script knowing the anchor internals.

### Events

| Event | Type | Fires when |
|---|---|---|
| `OnSaveRequest` | `EventHandler` | `RequestSave()` is called |
| `OnDisableRequest` | [`UnityEvent`](https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html) | `RequestDisable()` is called — wire it in the Inspector |

### Method summary

| Method | Returns | |
|---|---|---|
| [`RequestSave`](#requestsave) | `void` | <Badge>Unity component</Badge> |
| [`RequestDisable`](#requestdisable) | `void` | <Badge>Unity component</Badge> |
| [`CallOnSaveRequest`](#callonsaverequest) | `AnchorVisualization` | <Badge tone="accent">fluent</Badge> |

### RequestSave

<ApiBody kind="method" tags="Unity component">

```csharp
public void RequestSave();
```

Raises `OnSaveRequest`. Call from your save button/gesture to ask whatever subscribed (e.g. anchor-persistence logic) to save this anchor.

</ApiBody>

### RequestDisable

<ApiBody kind="method" tags="Unity component">

```csharp
public void RequestDisable();
```

Invokes the `OnDisableRequest` `UnityEvent`. Use it to tear down or hide the anchor visualization; wire the response in the Inspector.

</ApiBody>

### CallOnSaveRequest

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

```csharp
public AnchorVisualization CallOnSaveRequest(EventHandler handler);
```

Subscribes `handler` to `OnSaveRequest` and returns this instance, so you can chain configuration fluently.

<Params>
<Param name="handler" type="EventHandler">callback invoked on each save request</Param>
</Params>

<Returns type="AnchorVisualization">this instance, for chaining</Returns>

<Example inferred>

```csharp
// Subscribe fluently, then keep configuring on the same line.
anchorViz
    .CallOnSaveRequest((s, e) => Debug.Log("Anchor save requested"));
```

</Example>

</ApiBody>

## BoundaryVisualization

<Badge tone="type">class · MonoBehaviour</Badge> <Badge>Unity component</Badge> <Badge>RequireComponent</Badge>

```csharp
public class BoundaryVisualization : MonoBehaviour
```

**Namespace:** `AR51.Unity.SDK`

Builds a wall mesh plus an outline for a recorded play-area boundary. Requires a [`MeshFilter`](https://docs.unity3d.com/ScriptReference/MeshFilter.html) + [`MeshRenderer`](https://docs.unity3d.com/ScriptReference/MeshRenderer.html) on the same GameObject and expects a child [`LineRenderer`](https://docs.unity3d.com/ScriptReference/LineRenderer.html) for the outline. Set the fields **before `Start`** — the mesh is built at startup from `Points` and `Height`. If `Id` matches the active boundary's name the wall renders red; otherwise an auto-color is chosen. Feed it from a boundary source such as [`IBoundaryAdapter.GetPoints()`](/docs/sdk-api/unity-api/classes/adapters).

### Properties

<div className="apiPropTable">

| Property | Type | Description |
|---|---|---|
| `Id` | `string` | boundary identifier — matches the active boundary's name → renders red, else auto-color |
| `Points` | [`Vector3[]`](https://docs.unity3d.com/ScriptReference/Vector3.html) | ordered ground-plane outline points. ⚠️ **world-space, meters**. Fewer than 4 points skips the mesh |
| `Height` | `float` | wall height in **meters**, extruded along `+Y` |
| `Visible` | `bool` | get/set — toggles wall + outline rendering |

</div>

<Example inferred>

```csharp
// Visualize the platform boundary reported by the active boundary adapter.
var viz = boundaryGO.GetComponent<BoundaryVisualization>();
viz.Id     = BoundaryAdapterFactory.GetAdapter().BoundaryName;
viz.Points = BoundaryAdapterFactory.GetAdapter().GetPoints();   // world-space meters
viz.Height = 2.5f;                                              // meters
// Set before Start; the wall mesh is built at startup.
```

</Example>

## ConstrainPosition

<Badge tone="type">class · MonoBehaviour</Badge> <Badge>Unity component</Badge>

```csharp
public class ConstrainPosition : MonoBehaviour
```

**Namespace:** `AR51.Unity.SDK.Components`

A position-only follow constraint. Each `Update` it copies `Source`'s world position onto this GameObject (rotation and scale are left untouched). A null `Source` is a no-op.

### Properties

<div className="apiPropTable">

| Property | Type | Description |
|---|---|---|
| `Source` | [`Transform`](https://docs.unity3d.com/ScriptReference/Transform.html) | the transform to follow each frame; `null` = no-op |

</div>

<Example inferred>

```csharp
// Pin a label to a tracked joint's world position without inheriting its rotation.
labelGO.GetComponent<ConstrainPosition>().Source = headBoneTransform;
```

</Example>

## CustomHandsAdapter

<Badge tone="type">class · MonoBehaviour</Badge> <Badge>Unity component</Badge> <Badge tone="accent">IHandsAdapter</Badge>

```csharp
public class CustomHandsAdapter : MonoBehaviour, IHandsAdapter
```

**Namespace:** `AR51.Unity.SDK.Components`

An **in-scene** [`IHandsAdapter`](/docs/sdk-api/unity-api/classes/adapters) driven by Inspector-assigned `Transform`s instead of a device tracker. It samples the mapped transforms each request and reports them as [`HandJointInfo`](/docs/sdk-api/unity-api/classes/hand-data) with `Confidence = 1.0`, and can keep the wrist anchored to a tracked source. Joint arrays are assembled on `Awake`. Use it to puppet hands from authored/animated transforms, or as a stand-in when no hardware hand tracking is present.

:::tip
This is the scene-component counterpart to the registry-based adapters. For the adapter interface, the factory, and how the SDK resolves an active adapter per platform, see [Hands, controllers & boundary adapters](/docs/sdk-api/unity-api/classes/adapters).
:::

### Properties

<div className="apiPropTable">

| Property | Type | Description |
|---|---|---|
| `SourceDevice` | `string` | get-only — always `"CustomHandModel"` |
| `WristTrackingMode` | `WristTrackingModeType` | how the wrist is driven: `None` / `TrackActivePerson` / `TrackDeviceAdapter` |
| `LeftHand` | `HandMapping` | Inspector bone-transform mapping for the left hand |
| `RightHand` | `HandMapping` | Inspector bone-transform mapping for the right hand |

</div>

### Method summary

| Method | Returns | |
|---|---|---|
| [`GetRightJointInfos` / `GetLeftJointInfos`](#getrightjointinfos--getleftjointinfos) | [`HandJointInfo[]`](/docs/sdk-api/unity-api/classes/hand-data) | <Badge tone="accent">IHandsAdapter</Badge> |
| [`GetJoints`](#getjoints) | [`Transform[]`](https://docs.unity3d.com/ScriptReference/Transform.html) | <Badge>Unity component</Badge> |
| [`GetHand`](#gethand) | `HandMapping` | <Badge>Unity component</Badge> |

### GetRightJointInfos / GetLeftJointInfos

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

```csharp
public HandJointInfo[] GetRightJointInfos();
public HandJointInfo[] GetLeftJointInfos();
```

The `IHandsAdapter` snapshot methods. Each joint is sampled from the assigned transforms with `Confidence = 1.0`; order follows the [`HandJointType`](/docs/sdk-api/unity-api/classes/hand-data) enum (index = `(int)HandJointType`).

<Returns type="HandJointInfo[]" typeHref="/docs/sdk-api/unity-api/classes/hand-data">the hand's joints, index-ordered, each at full confidence</Returns>

</ApiBody>

### GetJoints

<ApiBody kind="method" tags="Unity component">

```csharp
public Transform[] GetJoints(HandType type);
```

The assembled joint transforms for a hand (wrist + fingers, SDK order).

<Params>
<Param name="type" type="HandType">which hand (left/right) — see [`HandType`](/docs/sdk-api/unity-api/classes/hand-data)</Param>
</Params>

<Returns type="Transform[]">the wrist + finger transforms in SDK joint order</Returns>

</ApiBody>

### GetHand

<ApiBody kind="method" tags="Unity component">

```csharp
public HandMapping GetHand(HandType type);
```

Returns the `HandMapping` for the given hand.

</ApiBody>

### Nested types

`[Serializable] HandMapping` holds the per-hand transform mapping (`Type`, `Source`, `Wrist`, and the per-finger groups). Each finger group — `ThumbJoints`, `IndexJoints`, `MiddleJoints`, `RingJoints`, `PinkyJoints` — is a serializable struct of `Transform` fields with a `Transform[] ToArray()` returning them base→tip. Assign these in the Inspector.

## FaceCamera

<Badge tone="type">class · MonoBehaviour</Badge> <Badge>Unity component</Badge>

```csharp
public class FaceCamera : MonoBehaviour
```

**Namespace:** `AR51.Unity.SDK.Components`

A yaw-only billboard. Each frame it rotates this GameObject about the Y axis to face the camera; pitch is ignored, so upright labels and panels stay level. Falls back to [`Camera.main`](https://docs.unity3d.com/ScriptReference/Camera-main.html) when `Camera` is unset; a null camera is a no-op.

### Properties

<div className="apiPropTable">

| Property | Type | Description |
|---|---|---|
| `Camera` | [`Camera`](https://docs.unity3d.com/ScriptReference/Camera.html) | target camera; falls back to `Camera.main`, `null` = no-op |

</div>

<Example inferred>

```csharp
// Keep a world-space name tag turned toward the player's view, staying upright.
tagGO.AddComponent<FaceCamera>();   // uses Camera.main by default
```

</Example>

## See also

- [Hands, controllers & boundary adapters](/docs/sdk-api/unity-api/classes/adapters) — the `IHandsAdapter` / `IBoundaryAdapter` interfaces and factories `CustomHandsAdapter` and `BoundaryVisualization` work with
- [`HandJointInfo`](/docs/sdk-api/unity-api/classes/hand-data) — the per-joint sample `CustomHandsAdapter` reports
- [`ObjectTransform`](/docs/sdk-api/unity-api/classes/objecttransform) — pose data for the object/transform consumers
- [Class index](/docs/sdk-api/unity-api/classes) — all Unity SDK types
