# Track Objects in C# (AR51.Net)

Receive the objects the AR 51 system tracks, such as props, with their **position** (meters) and **rotation**. Objects are defined in advance, in Mocap Studio — see [Tracked objects](/docs/mocap-studio/tracked-objects/).

## Receive objects

Object detection works exactly like [skeletons](/docs/csharp-api/skeletons/): subscribe to `ObjectReceived`, or read `StreamAsync` with `await foreach`.

```csharp
ar51.ObjectDetection.ObjectReceived += (_, e) =>
    Console.WriteLine($"{e.Object.Name} at {e.Object.Position} m, rotation {e.Object.Rotation}");
await ar51.StartAsync();
```

`ObjectReceived` fires **once per object per frame**, on the stream's background thread — keep handlers short.

## What a tracked object contains

<div className="apiTable">

| Member | What it is |
|---|---|
| `Id` | Tracking id, stable while the object stays tracked |
| `Name` | The object's name as defined in Mocap Studio — it also tells you what kind of object it is |
| `Position` | Position in **meters** (left-handed, X right, Y up, Z forward) |
| `Rotation` | Rotation, as a `System.Numerics.Quaternion` |
| `CaptureTime`, `ReceivedTime` | When the cameras captured it (server clock, UTC) and when you received it (local clock) |

</div>

A `TrackedObject` is immutable and safe to share across threads.

## Complete sample

Print every tracked object as it arrives. Press **Ctrl+C** to quit.

{/* SAMPLE:04-objects — generated from the ar51-net-samples repo; edit there */}
```csharp title="Program.cs"
// Print the tracked objects as they arrive. Objects are defined in Mocap Studio. Ctrl+C to quit.
using AR51.Net;

await using IAR51Client ar51 = AR51Client.Create();

// One event per object per frame, on the stream's background thread: keep handlers short.
ar51.ObjectDetection.ObjectReceived += (_, e) =>
{
    TrackedObject trackedObject = e.Object;
    Console.WriteLine($"{trackedObject.Name} ({trackedObject.Id}) at {trackedObject.Position} m, rotation {trackedObject.Rotation}");
};

await ar51.StartAsync();
Console.WriteLine("Receiving objects. Ctrl+C to quit.");

using var quit = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; quit.Cancel(); };
try { await Task.Delay(Timeout.Infinite, quit.Token); } catch (OperationCanceledException) { }
```

[View this sample on Bitbucket](https://bitbucket.org/ar51/ar51-net-samples/src/main/04-objects/) — clone the [samples repository](https://bitbucket.org/ar51/ar51-net-samples) to run it.
{/* /SAMPLE */}

## Reference

[`IObjectDetectionClient`](/docs/sdk-api/csharp-api/classes/iobjectdetectionclient/) · [`TrackedObject`](/docs/sdk-api/csharp-api/classes/trackedobject/) · [`ObjectDetectionClient`](/docs/sdk-api/csharp-api/classes/objectdetectionclient/)
