Get VR room-scale bounds w/ native Unity

Hi,

is there a way to get the currently set chaperone/guardian bounds (preferably in Unity units) from both SteamVR and Oculus using only native Unity code? Something in the XR namespace, maybe? I was not able to find it :-(

Philip

at least in steamvr there is SteamVR/Scripts/SteamVR_PlayArea.cs
which seems to do some kind of mesh bounds from OpenVR.Chaperone.GetPlayAreaRect?

havent tested that what it actually returns…

Both the SteamVR and the Oculus plugins support getting the play area size; however, my question was/is about getting said size using only Unity API.

I know we have access to it natively, but I don't see any developer APIs for it. I want to get that in for 2019.3, it really should be available without plugins.

4 Likes

Thanks for the honest answer, and it would be totally great to have that. I keep my fingers crossed, having it in 2019 would be perfect.

Hi,
Is there any update on this point ?
It would be very helpful.
best,
Norel

1 Like

There is!
bool UnityEngine.XR.XRInputSubsystem.TryGetBoudnaryPoints(Vector3[ ])
These are floor height, clockwise wound boundary points returned from the SDK.
And
UnityEngine.XR.XRInputSubsystem.BoundaryChanged event
Notifies you when the boundary changes, so you know to get a new version.
This can occur on a Recenter, or if changed by the user.

3 Likes

Is there a example for this? And how to use it?

Thanks a lot StayTalm !

This is the way I managed to use this function :
- Stopped using Legacy XR (Project Settings > Player > XR)
- Started using XR Management package, as described here
- Placed TrackedPoseDrivers on cameras since they are no longed added automatically
- Used this code :

List<InputDevice> inputDevices = new List<InputDevice>();
InputDevices.GetDevicesWithRole(InputDeviceRole.Generic, inputDevices);
InputDevice hMDDevice = inputDevices[0];
XRInputSubsystem XRIS = hMDDevice.subsystem;
List<Vector3> boundaryPoints = new List<Vector3>();
XRIS.TryGetBoundaryPoints(boundaryPoints);

And I get access to my Guardian boudaries, without using OVRManager, which is great.

However, in the headset, the image is only displayed on left eye (right eye is blue). I couldn't manage to fix it, even by using Single Pass Rendering.
The display also seems significatively slower than before.
Any hints on how I could solve this ?

I'm using an Oculus Rift S on Windows, with Unity 2019.3.0f1, and rendering with Universal RP.

Best,
Norel

1 Like

I found that in 2019.3.0f5 I had to use the “3D” pipeline. When I used Universal RP with the XR Managment system, it only rendered in the left eye of my Oculus Quest. From what I could find, it seems like the Universal RP isn’t quite ready yet for VR development.

Bonus: check out the XR Managment Example repo Unity is developing. you might find it useful.
https://github.com/Unity-Technologies/XR-Interaction-Toolkit-Examples

Confirmed. the One-eye bug is in URP 7.1.8 and will be fixed in 7.2.0 which was supposed to release two days ago, but they had a regression in QA so it’ll probably be out next week sometime.

Is there a way to get this to work with Oculus Quest via Link Cable (or Wireless via Virtual Desktop).
I am trying to make a large roomscale application.
The Quast Guardian System is always correct. But each Time i start the Experience the Player gets a random Position and Rotation. So I want to use the Guarding System as referenz to Calibrate the Player. But when I try to get the Boundarypoints the List is always empty.

2 Likes

I have the same Problem. Also Quest, always getting an empty list. I detailed it in another thread, so I’m posting here too so both threads are cross linked, just in case ^^
( https://forum.unity.com/threads/can-we-reuse-user-s-vr-boundaries.818331/#post-5558206 )

In your case, have you tried it with the “XRInputSubsystem.TryRecenter” after your application starts?

hey guys, you can fix your rendering prob with updating the ur pipeline to 7.2.1 - that works for me. But unfortunately I didn´t get the boundary points, list is always empty. Do you have any suggestions?

I had success with the following method

public GameObject wallMarker;
//Check if the boundary is configured
bool configured = OVRManager.boundary.GetConfigured();
        if (configured)
        {
            //Grab all the boundary points. Setting BoundaryType to OuterBoundary is necessary
            Vector3[] boundaryPoints = OVRManager.boundary.GetGeometry(OVRBoundary.BoundaryType.OuterBoundary);
       
             //Generate a bunch of tall thin cubes to mark the outline
            foreach (Vector3 pos in boundaryPoints)
            {      
                Instantiate(wallMarker, pos, Quaternion.identity);
            }
        }

Edit: This will obviously only work for Oculus

Has anyone tried getting the boundary with the OpenVR plugin? Using the following code:

var input = XRGeneralSettings.Instance.Manager.activeLoader.GetLoadedSubsystem<XRInputSubsystem>();
List<Vector3> boundaryPoints = new List<Vector3>();
if (input.TryGetBoundaryPoints(boundaryPoints))
{
    Debug.Log(boundaryPoints.Count);
}

TryGetBoundaryPoints returns true, but does not populate the list of points. When running with the Oculus loader, it does correctly populate the points in the correct positions.

I am seeing the same behavior on my end. Nothing fails, but always returns and empty list.

Since I need to use OpenXR for other things I can’t switch to OVR. Were you able to fix it?

1 Like

Any updates on this @Cazforshort @Iron-Warrior ? :confused:

For me starting the XRInputSubsystem did the trick, as it turned out it was (somehow) not running. Doing so will automatically draw the bounds of the play area and recenter the XRRig in the play area:

var input =
List<XRInputSubsystem> inputSubsystems = new List<XRInputSubsystem>();
        SubsystemManager.GetInstances<XRInputSubsystem>(inputSubsystems);

        if (inputSubsystems.Count > 0)
        {
            XRInputSubsystem inputSubsystem = inputSubsystems[0];
            if (!inputSubsystem.running)
            {
                // Start the subsystem if not started yet
                inputSubsystem.Start();
            }
            List<Vector3> boundaryPoints = new List<Vector3>();
            if (inputSubsystem.TryGetBoundaryPoints(boundaryPoints))
            {
                Debug.Log(boundaryPoints.Count);
            }
        }

P.S.: If you only want access the points you can stop the subsystem and reset the position and rotation of your Rig afterwards.

1 Like

Great! I wonder why it is so un-obvious.