Tracking Data¶
XRXP supports both discrete events and continuous spatial tracking.
Object tracking¶
Add XRXPObjectTracker to any GameObject you want to follow during a session.
Common uses:
- head and hands
- tools and props
- gaze targets or UI objects
- experiment-specific interactables
Key tracker fields¶
| Field | Meaning |
|---|---|
Category | Group name such as Body, Prop, or UI |
ObjectName | Stable identifier for the tracked object |
TraceFrequency | Number of frames between samples; 1 means every frame, 0 disables recording |
TracingEnabled | Enable or disable capture |
Example¶
var tracker = gameObject.AddComponent<XRXPObjectTracker>();
tracker.Category = "Body";
tracker.ObjectName = "RightHand";
tracker.TraceFrequency = 5;
The tracker automatically calls AddInternalEvent with SystemType.WorldPosition on LateUpdate. It only records when XRXPManager.IsReady, TracingEnabled is true, and a session is active.
Event types you will usually combine¶
- Log events — discrete actions formatted as Actor, Verb, Object with optional properties
- Internal events — continuous system or transform data recorded at a point in time, grouped under a system
- Questions — questionnaire answers with optional properties
- Media events — files (images, audio, video, documents) produced during the experiment
How internal systems and events work¶
When you call AddInternalEvent, the SDK:
- checks if an InternalSystem with that
systemNamealready exists for the current session - if not, creates one (linked to the session, user, and system type) and sends it as a trace
- creates an InternalEvent record with the timestamp, property name, and value, linked to that system
One system groups many events. For example, a "BodyTracking" system with SystemType.WorldPosition can have events for "Head", "LeftHand", and "RightHand" — all under the same system.
using XRXP.Recorder.Models;
// All three events belong to the same "BodyTracking" system
XRXPManager.Recorder.AddInternalEvent(
SystemType.WorldPosition, "BodyTracking", "Head",
new WorldPosition(head.position, head.rotation)
);
XRXPManager.Recorder.AddInternalEvent(
SystemType.WorldPosition, "BodyTracking", "LeftHand",
new WorldPosition(leftHand.position, leftHand.rotation)
);
XRXPManager.Recorder.AddInternalEvent(
SystemType.WorldPosition, "BodyTracking", "RightHand",
new WorldPosition(rightHand.position, rightHand.rotation)
);
System types¶
| SystemType | Value class | Use case |
|---|---|---|
WorldPosition | WorldPosition(Vector3, Quaternion) | Track position and rotation of objects, body parts, gaze |
QuantitativeValue | Any class implementing Jsonable | Track numeric signals: speed, heartbeat, score, distance |
Jsonable is an interface with a single method string ToJSON(). WorldPosition implements it. For QuantitativeValue, create your own class:
using XRXP.Recorder.Models;
public class QuantitativeValue : Jsonable
{
public float Value;
public string Unit;
public QuantitativeValue(float value, string unit)
{
Value = value;
Unit = unit;
}
public string ToJSON()
{
return UnityEngine.JsonUtility.ToJson(this);
}
}
Then use it:
XRXPManager.Recorder.AddInternalEvent(
SystemType.QuantitativeValue, "Biometrics", "HeartRate",
new QuantitativeValue(72f, "bpm")
);
Naming guidance¶
Use a stable schema from the start of a study:
- actors:
User,System,NPC_Guide - verbs:
clicked,grabbed,entered,completed - objects: specific object or state names
Consistent naming makes the dashboard much easier to filter and export later.