XRPositionalTracker
Shared state for named poses and tracking.
XRPositionalTracker stores state supplied by a tracking provider to XRServer. It is not an Entity or a physics body. Constructing it registers no device and starts no session. XRControllerTracker represents a controller; use XREntity3D or XRController3D in gameplay rigs.
HasPose checks entry existence. InvalidatePose retains the entry, last transform, velocities and confidence while clearing HasTrackingData. SetPose updates the same object and validates it again; even Confidence=None does not clear that flag. Assess data eligibility separately from entry existence.
This executed example copies the raw transform only when tracking is available. It adds no WorldScale, reference frame or gameplay origin and does not assess tracking quality:
using Reckfell;
public static class TrackedPoseReader
{
// Raw tracking-space pose, not a world transform or a tracking-quality test.
public static bool TryRead(
XRPositionalTracker tracker, StringName poseName, out Transform3D transform)
{
transform = Transform3D.Identity;
if (tracker is null) return false;
// Shared tracker state: do not dispose its cached C# wrapper here.
var pose = tracker.GetPose(poseName);
if (pose is null || !pose.HasTrackingData) return false;
transform = pose.Transform;
return true;
}
}GetPose and event arguments contain shared state. C# may reuse the wrapper for one native object: do not Dispose/use using on a borrowed pose. Testing showed this invalidates another held reference. Copy Transform, velocities and flags for a snapshot.
PoseChanged fires on every SetPose; PoseLostTracking on every InvalidatePose of an existing entry, including repeats. This differs from deduplicated TrackingChanged on XREntity3D. Pose loss does not reset stored input or create ButtonReleased.
The current C# SDK marks GetInput/SetInput Obsolete even through XRControllerTracker. Gameplay reads XRController3D; native Call was used only in an isolated synthetic-provider check. State and the example were checked without a real headset or tracking-quality assessment. Setup: XR components.
Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.
Constructors1
XRPositionalTrackerConstructor
public XRPositionalTracker();Creates a state container with no poses, an empty Profile, Hand=Unknown and Type=Unknown. Does not register with XRServer or discover a device. Use XRControllerTracker for a controller.
Properties2
HandProperty
public XRPositionalTracker.TrackerHand Hand { get; set; }Hand assignment, initially Unknown. Use Unknown, Left or Right; Max is the enum bound, not a device value. The setter checks bounds. Not inferred automatically from Name; creates no pose and emits no ProfileChanged.
ProfileProperty
public string Profile { get; set; }Profile string, initially empty. For OpenXR usually an interaction-profile path; the setter does not validate format or support. ProfileChanged fires only when the string changes and carries the new profile. Does not create a device or switch its capabilities.
Methods10
GetInputVariant · Deprecated
public Variant GetInput(StringName name);Returns a Variant by internal action name, or Nil. The current C# SDK marks it Obsolete, including when inherited by XRControllerTracker. For gameplay use XRController3D.GetInput; direct access on a base XRPositionalTracker also produces a native warning. Does not check pose or focus.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
nameExact internal action name; not LocalizedName or ordinary InputMap.
VariantStored-type Variant or Nil; dispose the returned Variant wrapper with using.
GetPoseXRPose
public XRPose GetPose(StringName name);Returns shared named-pose state or null. Repeated SetPose updates the same object; not a snapshot. C# may reuse the same wrapper: do not Dispose/use using on borrowed pose state that other references may read. Copy Transform and required values for a snapshot; check HasTrackingData.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
nameExact pose name, such as grip or aim; not a left_hand/right_hand tracker name.
XRPoseShared pose or null. Do not dispose the borrowed C# wrapper; copy values for a snapshot.
GetTrackerHandXRPositionalTracker.TrackerHand
public XRPositionalTracker.TrackerHand GetTrackerHand();Returns stored hand assignment, initially Unknown. Does not establish tracking data availability.
XRPositionalTracker.TrackerHandStored hand; initially Unknown.
GetTrackerProfilestring
public string GetTrackerProfile();Returns the stored profile string, initially empty. Not a tracker name, hand or proof of device support.
stringStored profile; initially an empty string.
HasPosebool
public bool HasPose(StringName name);Checks whether a named pose entry exists. Remains true after InvalidatePose because the entry is retained. To use the data, inspect GetPose(name) and that pose’s HasTrackingData.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
nameExact pose name, such as grip or aim; not a left_hand/right_hand tracker name.
booltrue when an entry exists, including one with lost tracking.
InvalidatePosevoid
public void InvalidatePose(StringName name);For an existing pose, clears HasTrackingData and emits PoseLostTracking on every call, including repeats. Does not remove the entry, zero transform/velocities/confidence or reset input. An unknown name does nothing. The next SetPose validates the entry again.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
nameExact pose name, such as grip or aim; not a left_hand/right_hand tracker name.
SetInputvoid · Deprecated
public void SetInput(StringName name, Variant value);Stores a value by action name; events occur only for changed values and only for Bool, Float or Vector2. Float does not synthesize threshold-based ButtonPressed. The C# SDK marks this method Obsolete even through XRControllerTracker; not a gameplay-input API. The tracking provider owns state; gameplay reads XRController3D. QA used native Call only for synthetic data.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
value | Variant | — |
nameExact internal action name; not LocalizedName or ordinary InputMap.
valueAction value. Events support Bool, Float and Vector2; provider data, not keyboard simulation.
SetPosevoid
public void SetPose(StringName name, Transform3D transform, Vector3 linearVelocity, Vector3 angularVelocity, XRPose.TrackingConfidenceEnum trackingConfidence);Creates a missing pose entry or updates the existing object. Stores transform, velocities, confidence and HasTrackingData=true; emits PoseChanged on every call, even for identical values. Confidence=None does not itself clear HasTrackingData. Intended for the tracking provider; gameplay should not replace real-device state.
| Name | Type | Default |
|---|---|---|
name | StringName | — |
transform | Transform3D | — |
linearVelocity | Vector3 | — |
angularVelocity | Vector3 | — |
trackingConfidence | XRPose.TrackingConfidenceEnum | — |
nameExact pose name, such as grip or aim; not a left_hand/right_hand tracker name.
transformProvider tracking-space transform. Stored without adding the gameplay origin; not the character GlobalTransform.
linearVelocityLinear velocity in provider conventions; stored as supplied, not computed from previous poses.
angularVelocityAngular velocity in provider conventions; stored as supplied.
trackingConfidenceConfidence for the entry. None does not prevent SetPose setting HasTrackingData=true; these are distinct fields.
SetTrackerHandvoid
public void SetTrackerHand(XRPositionalTracker.TrackerHand hand);Hand assignment, initially Unknown. Use Unknown, Left or Right; Max is the enum bound, not a device value. The setter checks bounds. Not inferred automatically from Name; creates no pose and emits no ProfileChanged.
| Name | Type | Default |
|---|---|---|
hand | XRPositionalTracker.TrackerHand | — |
handUnknown, Left or Right; Max is not a valid hand.
SetTrackerProfilevoid
public void SetTrackerProfile(string profile);Profile string, initially empty. For OpenXR usually an interaction-profile path; the setter does not validate format or support. ProfileChanged fires only when the string changes and carries the new profile. Does not create a device or switch its capabilities.
| Name | Type | Default |
|---|---|---|
profile | string | — |
profileProfile string to store. The setter does not verify runtime support; repeating it emits no event.
Signals and events7
ButtonPressedEvent
public event XRPositionalTracker.ButtonPressedEventHandler ButtonPressed;Emitted for a changed Bool=true write. Repeated true emits nothing; Float does not automatically become a press. Carries the internal action name, not a display label.
| Name | Type | Default |
|---|---|---|
actionName | string | — |
actionNameInternal action name, such as select; not a label or controller-component path.
ButtonReleasedEvent
public event XRPositionalTracker.ButtonReleasedEventHandler ButtonReleased;Emitted for a changed Bool=false write. Pose loss does not reset input or emit a release; clear gameplay interaction state separately.
| Name | Type | Default |
|---|---|---|
actionName | string | — |
actionNameInternal action name, such as select; not a label or controller-component path.
InputFloatChangedEvent
public event XRPositionalTracker.InputFloatChangedEventHandler InputFloatChanged;Passes a changed Float action value. The C# value parameter is double. Creates no button-press events and adds no dead zone.
| Name | Type | Default |
|---|---|---|
actionName | string | — |
value | double | — |
actionNameInternal action name, such as select; not a label or controller-component path.
valueNew double value of the Float action.
InputVector2ChangedEvent
public event XRPositionalTracker.InputVector2ChangedEventHandler InputVector2Changed;Passes a changed Vector2 value. This event’s parameter is named vector; do not confuse it with value on XRController3D.InputVector2Changed. Applies no normalization or dead zone.
| Name | Type | Default |
|---|---|---|
actionName | string | — |
vector | Vector2 | — |
actionNameInternal action name, such as select; not a label or controller-component path.
vectorNew Vector2 without normalization or a dead zone.
PoseChangedEvent
public event XRPositionalTracker.PoseChangedEventHandler PoseChanged;Passes the shared pose object after every SetPose, even if values are identical. A provider update, not necessarily a coordinate change. Do not dispose or mutate the supplied pose; copy required fields for long-term storage.
| Name | Type | Default |
|---|---|---|
pose | XRPose | — |
poseShared pose state. Do not mutate or dispose it; copy required values when retaining data.
PoseLostTrackingEvent
public event XRPositionalTracker.PoseLostTrackingEventHandler PoseLostTracking;Passes the retained pose with HasTrackingData already false. Repeated InvalidatePose emits again. Differs from deduplicated TrackingChanged on XREntity3D. Previous coordinates remain available but do not establish a current pose.
| Name | Type | Default |
|---|---|---|
pose | XRPose | — |
poseShared pose state. Do not mutate or dispose it; copy required values when retaining data.
ProfileChangedEvent
public event XRPositionalTracker.ProfileChangedEventHandler ProfileChanged;Emitted when Profile changes. The role parameter actually contains the new profile string, not Left/Right. Repeating the same profile emits nothing.
| Name | Type | Default |
|---|---|---|
role | string | — |
roleNew profile string; the historical argument name does not mean hand assignment.
XRPositionalTracker.TrackerHand
| Value | Description |
|---|---|
Left = 1 | This tracker is the left hand controller. |
Max = 3 | Represents the size of the |
Right = 2 | This tracker is the right hand controller. |
Unknown = 0 | The hand this tracker is held in is unknown or not applicable. |