OpenXRPlaneTracker
Plane with local geometry and cached collision shapes.
Plane data: BoundsSize, semantic label/alignment and optional polygon mesh. GetMesh/GetShape build caches but add no visual Entities or collisions. Geometry is XY; apply GetMeshOffset to a shared child Entity3D rather than adding an unconditional floor rotation.
Use MeshChanged to refresh mesh/shape, but origin-only SetMeshData emits no such event: read the offset every frame while tracking is valid. Repeating GetShape with another thickness returns the existing cached shape. Empty indices mean a fan, not general concave-polygon triangulation.
Executed example and setup. Windows headless XR-off covered synthetic metadata/client logic: 23 API cases and an earlier 20 helper checks. Real discovery, entity/context RIDs, persistence, headsets and imagery remain untested. Do not dispose provider-owned trackers/poses/cached wrappers; dispose a newly owned tracker after use.
Declarations checked against C# SDK 1.0.0. Expand a name to see declarations and documentation.
Constructors1
OpenXRPlaneTrackerConstructor
public OpenXRPlaneTracker();Creates a caller-owned RefCounted tracker without starting OpenXR, registering with XRServer or detecting anything. Base state is Paused, category Anchor, entity/context RIDs empty. Real applications normally use the borrowed provider-registered tracker rather than a synthetic resource. Release your own instance after removing owned references/registration.
Properties3
BoundsSizeProperty
public Vector2 BoundsSize { get; set; }Rectangular bounds in local XY, initially Vector2.Zero. The setter applies a change only when either component differs by >0.001. Without polygon data it clears caches and emits MeshChanged; with polygon data the bounds do not replace the mesh. Both components must be positive for rectangular fallback.
PlaneAlignmentProperty
public OpenXRSpatialComponentPlaneAlignmentList.PlaneAlignment PlaneAlignment { get; set; }Plane orientation metadata, default HorizontalUpward even without detector data. The setter stores it without rotating geometry or emitting MeshChanged. Does not establish a detected floor, tracking or actual runtime classification.
PlaneLabelProperty
public string PlaneLabel { get; set; }Semantic plane label, or empty without data. The setter also copies it to tracker Description; it rebuilds no mesh/shape and emits no MeshChanged. Do not interpret empty/unknown labels as floor; label support depends on the runtime.
Methods14
ClearMeshDatavoid
public void ClearMeshData();Clears polygon vertices/indices, origin and mesh/shape caches while preserving BoundsSize. A later GetMesh/GetShape may therefore return rectangular fallback rather than null. Emits MeshChanged only if polygon data existed; after explicit clearing refresh owned mesh/collider regardless of the event.
GetBoundsSizeVector2
public Vector2 GetBoundsSize();Rectangular bounds in local XY, initially Vector2.Zero. The setter applies a change only when either component differs by >0.001. Without polygon data it clears caches and emits MeshChanged; with polygon data the bounds do not replace the mesh. Both components must be positive for rectangular fallback.
Vector2Rectangular bounds in local XY, initially Vector2.Zero. The setter applies a change only when either component differs by >0.001. Without polygon data it clears caches and emits MeshChanged; with polygon data the bounds do not replace the mesh. Both components must be positive for rectangular fallback.
GetIndicesint[]
public int[] GetIndices();Stored triangle indices, or empty. SetMeshData without indices populates a generated fan rather than the original contour; rectangular fallback does not populate this list. The C# int[] is readable/copied data, not an in-place tracker editor.
int[]Stored triangle indices, or empty. SetMeshData without indices populates a generated fan rather than the original contour; rectangular fallback does not populate this list. The C# int[] is readable/copied data, not an in-place tracker editor.
GetMeshMesh
public Mesh GetMesh();Lazily builds/caches a mesh from polygon data or positive BoundsSize; null without either. Geometry is local XY, not world space; apply GetMeshOffset separately. The returned wrapper is borrowed: do not Dispose. MeshChanged requires refreshing your own MeshInstance3D.Mesh; tracker setters do not update your Entity automatically.
MeshLazily builds/caches a mesh from polygon data or positive BoundsSize; null without either. Geometry is local XY, not world space; apply GetMeshOffset separately. The returned wrapper is borrowed: do not Dispose. MeshChanged requires refreshing your own MeshInstance3D.Mesh; tracker setters do not update your Entity automatically.
GetMeshOffsetTransform3D
public Transform3D GetMeshOffset();Geometry transform relative to default pose: for polygon data, inverse(raw pose) × mesh origin, then translation scaled by WorldScale. Identity without polygon data. Apply to a shared mesh/collider child Entity3D. Origin-only updates may emit no MeshChanged; refresh the offset every frame while tracking is valid. Execution was limited to WorldScale=1.
Transform3DGeometry transform relative to default pose: for polygon data, inverse(raw pose) × mesh origin, then translation scaled by WorldScale. Identity without polygon data. Apply to a shared mesh/collider child Entity3D. Origin-only updates may emit no MeshChanged; refresh the offset every frame while tracking is valid. Execution was limited to WorldScale=1.
GetPlaneAlignmentOpenXRSpatialComponentPlaneAlignmentList.PlaneAlignment
public OpenXRSpatialComponentPlaneAlignmentList.PlaneAlignment GetPlaneAlignment();Plane orientation metadata, default HorizontalUpward even without detector data. The setter stores it without rotating geometry or emitting MeshChanged. Does not establish a detected floor, tracking or actual runtime classification.
OpenXRSpatialComponentPlaneAlignmentList.PlaneAlignmentPlane orientation metadata, default HorizontalUpward even without detector data. The setter stores it without rotating geometry or emitting MeshChanged. Does not establish a detected floor, tracking or actual runtime classification.
GetPlaneLabelstring
public string GetPlaneLabel();Semantic plane label, or empty without data. The setter also copies it to tracker Description; it rebuilds no mesh/shape and emits no MeshChanged. Do not interpret empty/unknown labels as floor; label support depends on the runtime.
stringSemantic plane label, or empty without data. The setter also copies it to tracker Description; it rebuilds no mesh/shape and emits no MeshChanged. Do not interpret empty/unknown labels as floor; label support depends on the runtime.
GetShapeShape3D
public Shape3D GetShape(float thickness = 0.01f);Lazily builds/caches Shape3D: polygon data use ConcavePolygonShape3D, positive BoundsSize use BoxShape3D, otherwise null. Borrowed wrapper; do not Dispose. Thickness defaults to 0.01; supply a finite positive value. Once cached, a different thickness does not rebuild it; clear/update data or create your own shape. The getter enables no collisions.
| Name | Type | Default |
|---|---|---|
thickness | float | 0.01f |
thicknessFinite positive thickness, default 0.01. An already cached shape ignores a new value.
Shape3DLazily builds/caches Shape3D: polygon data use ConcavePolygonShape3D, positive BoundsSize use BoxShape3D, otherwise null. Borrowed wrapper; do not Dispose. Thickness defaults to 0.01; supply a finite positive value. Once cached, a different thickness does not rebuild it; clear/update data or create your own shape. The getter enables no collisions.
GetVerticesVector2[]
public Vector2[] GetVertices();Stored polygon vertices in local XY, or empty; rectangular fallback does not populate this list. The C# getter returns a Vector2[] copy, so modifying it does not edit the tracker. Use SetMeshData to update.
Vector2[]Stored polygon vertices in local XY, or empty; rectangular fallback does not populate this list. The C# getter returns a Vector2[] copy, so modifying it does not edit the tracker. Use SetMeshData to update.
SetBoundsSizevoid
public void SetBoundsSize(Vector2 boundsSize);Rectangular bounds in local XY, initially Vector2.Zero. The setter applies a change only when either component differs by >0.001. Without polygon data it clears caches and emits MeshChanged; with polygon data the bounds do not replace the mesh. Both components must be positive for rectangular fallback.
| Name | Type | Default |
|---|---|---|
boundsSize | Vector2 | — |
boundsSizeRectangular bounds in local XY, initially Vector2.Zero. The setter applies a change only when either component differs by >0.001. Without polygon data it clears caches and emits MeshChanged; with polygon data the bounds do not replace the mesh. Both components must be positive for rectangular fallback.
SetMeshData2 overloads
public void SetMeshData(Transform3D origin, Vector2[] vertices, int[] indices = null);Assigns local XY vertices, their origin transform and triangle indices. Requires >=3 vertices; fewer clear existing polygon data. Empty indices generate a vertex-zero fan, so supply valid triangulation for concave contours. Validate index bounds and triangle multiples yourself. Geometry changes invalidate mesh/shape and emit MeshChanged; changing only origin with equal arrays emits no event.
| Name | Type | Default |
|---|---|---|
origin | Transform3D | — |
vertices | Vector2[] | — |
indices | int[] | null |
originPolygon-data transform in tracking space; do not pass a global transform without conversion. Changing origin alone may emit no MeshChanged.
verticesAt least three local XY vertices. Supply explicit triangle indices for a concave polygon.
indicesTriangle indices, a multiple of three and all within vertices. Empty enables a vertex-zero fan.
public void SetMeshData(Transform3D origin, ReadOnlySpan<Vector2> vertices, ReadOnlySpan<int> indices);Assigns local XY vertices, their origin transform and triangle indices. Requires >=3 vertices; fewer clear existing polygon data. Empty indices generate a vertex-zero fan, so supply valid triangulation for concave contours. Validate index bounds and triangle multiples yourself. Geometry changes invalidate mesh/shape and emit MeshChanged; changing only origin with equal arrays emits no event.
| Name | Type | Default |
|---|---|---|
origin | Transform3D | — |
vertices | ReadOnlySpan<Vector2> | — |
indices | ReadOnlySpan<int> | — |
originPolygon-data transform in tracking space; do not pass a global transform without conversion. Changing origin alone may emit no MeshChanged.
verticesAt least three local XY vertices. Supply explicit triangle indices for a concave polygon.
indicesTriangle indices, a multiple of three and all within vertices. Empty enables a vertex-zero fan.
SetPlaneAlignmentvoid
public void SetPlaneAlignment(OpenXRSpatialComponentPlaneAlignmentList.PlaneAlignment planeAlignment);Plane orientation metadata, default HorizontalUpward even without detector data. The setter stores it without rotating geometry or emitting MeshChanged. Does not establish a detected floor, tracking or actual runtime classification.
| Name | Type | Default |
|---|---|---|
planeAlignment | OpenXRSpatialComponentPlaneAlignmentList.PlaneAlignment | — |
planeAlignmentPlane orientation metadata, default HorizontalUpward even without detector data. The setter stores it without rotating geometry or emitting MeshChanged. Does not establish a detected floor, tracking or actual runtime classification.
SetPlaneLabelvoid
public void SetPlaneLabel(string planeLabel);Semantic plane label, or empty without data. The setter also copies it to tracker Description; it rebuilds no mesh/shape and emits no MeshChanged. Do not interpret empty/unknown labels as floor; label support depends on the runtime.
| Name | Type | Default |
|---|---|---|
planeLabel | string | — |
planeLabelSemantic plane label, or empty without data. The setter also copies it to tracker Description; it rebuilds no mesh/shape and emits no MeshChanged. Do not interpret empty/unknown labels as floor; label support depends on the runtime.
Signals and events1
MeshChangedEvent
public event Action MeshChanged;Geometry/some-cache change signal; reassign mesh/shape to your visual and physics Entities. Does not report all metadata or origin-only updates. Refresh GetMeshOffset separately while tracking is valid; do not assume one signal per operation.