Search Unity

  1. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  2. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  3. Participate with students all over the world and build projects to teach people. Join now!
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

OpenVR - How to reset camera properly?

Discussion in 'AR/VR (XR) Discussion' started by Todd-Wasson, Jul 22, 2016.

  1. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    UnityEngine.VR.InputTracking.Recenter() seems to work differently for the Rift SDK than it does in OpenVR. With the older Rift setup (Unity 5.3) the recenter puts your head at the origin. With the new system it either isn't working at all or it's resetting it to the floor. My game is a driving game so when somebody resets the VR headset I need it to pop to the driver's head. This no longer works, instead it places the feet at the driver's head and you're now standing on top of that. The camera doesn't go where I want it to in Unity 5.4, it's adding the person's height to it. That makes sense for a standing game but not for a sit down game.

    Is there a quick and easy way to fix that or is resetting the camera in OpenVR going to be trouble?
     
  2. Ed-unity

    Ed-unity

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    275
    When InputTracking.Recenter is called, we are essentially calling OpenVR's IVRSystem::ResetSeatedZeroPose.
    https://github.com/ValveSoftware/openvr/wiki/IVRSystem::ResetSeatedZeroPose

    This will only happen if SteamVR is set to a seated or standalone experience, it shouldn't do anything if the experience is set to room scale. This is noted in our ScriptingReference.

    It shouldn't pop to the ground or double. It should just recenter the X and Z rotation. What happens if you try this in a new scene with just a couple objects for reference and a Camera?
     
  3. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Thanks, Ed. I must have misinterpreted what it was doing. What you said makes sense, I think it might have just been centering the rotation. The trouble is that in OpenVR my viewpoint is as though I'm standing on top of the game driver's head (probably according to my floor to camera distance in SteamVR relative to....what I'm not sure) instead of my head being positioned at the game driver's head like it worked in 5.3 (not OpenVR).

    Not sure what I can do to restore it to how it worked before OpenVR where calling InputTracking.Recenter would reset the position and horizontal plane rotation to the game driver's head facing toward the front of the vehicle. Do I have to simply tell my customers to configure their SteamVR a certain way for this to work? That could potentially be a lot of extra support and frustration for them having to go fiddle with their SteamVR settings just to run my game comfortably while sitting.

    I've been up for 34 hours straight so will have to look at this tomorrow. Brain is mush now.:rolleyes:
     
  4. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Found this. Haven't tried it myself yet.

    http://skydomestudios.nl/dont-let-go-and-cross-hmd-development/


    ----------------
    Reset Seated Position
    When making a seated experience like Don’t Let Go it’s often necessary to have the user Reset the Orientation / position. This is to make sure the user’s virtual and real body line up correctly.

    To do this you can call the Unity Implementation like this:
    UnityEngine.VR.InputTracking.Recenter();

    This will work on the Oculus, but does nothing on OpenVR.
    So for the OpenVR SDK I used the following:

    Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    Valve.VR.OpenVR.Compositor.SetTrackingSpace(Valve.VR.ETrackingUniverseOrigin.TrackingUniverseSeated);
    ----------------

    On a separate note, am I misunderstanding the OpenVR versus Oculus lib setting in the Unity 5.4 beta? I was under the impression that the OpenVR library was for both Oculus and Vive. Is this not correct? If my title is supposed to support Vive and Oculus, do I need to include both libraries? The above post seems to suggest this is indeed the case. If so this might explain the water reflection problems I've been having in the beta with OpenVR only + Rift headset. If I include both libraries my Rift water reflection problems disappear and my head position is correct. That'd just leave me figuring out the Vive specific camera positioning per the above post by the looks of it.
     
  5. Ed-unity

    Ed-unity

    Unity Technologies

    Joined:
    Nov 18, 2013
    Posts:
    275
    Hey Todd, sorry for the delay in response.
    Technically you do not need to include both OpenVR and Oculus in your drop down to have your project work with both, but it is recommended that you do. The reason being that OpenVR extends the Oculus API, where as Oculus Native will directly communicate with the Oculus API making it a bit more reliable and faster. If you are only including OpenVR, We won't go through the Oculus recenter code, so even when using Oculus, it will call OpenVR.System.ResetSeatedZeroPose(). So, it could give you different results between the two.

    As a side note, I believe as the Developer you can force the experience setting to seated or room scale, without needing the User to change their settings. I'm not sure the specific call for OpenVR.
     
    Morseliot likes this.
  6. Fattie

    Fattie

    Joined:
    Jul 5, 2012
    Posts:
    375
    This works!

    Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    Valve.VR.OpenVR.Compositor.SetTrackingSpace(

    Valve.VR.ETrackingUniverseOrigin.TrackingUniverseSeated);

    However for us, After that, you sort of have to again move the camera to where it should be, that is to say the "user's" head.

    So, you have a vehicle model. There is a model of the driver Sally, with her hands on the wheel and so on. Have an empty Transform with the exact desired position and rotation of the camera POV, call it SallyPOV. (So, for example on the bridge of sally's nose and looking ahead.)

    Step 1: make a note of the vehicle rotation, temp = vehicle.rotation, and set the vehicle.rotation = Quaternion.identity so that the car/sally is pointing along z-forward zero (also set Sally's sitting straight ahead, if she moves around, as relevant)

    Step 2: do the "Todd Wassen miracle solution"

    Step 3. now set the position/rotation of the camera-holder to the same as SallyPOV. {Aside - of course, in general you have to move/twist a VR camera via a GameObject which holds the camera, you can't just move/twist a VR camera.}

    Step 4. return the overall car to vehicle.rotation = temp

    (note - some have reported you must wait a frame or two before the move in point 3; moves of wrappers; we found it worked without that.)

    A huge THANK YOU to @Todd-Wasson.
    Thank you so much.


    Note that Unity's UnityEngine.VR.InputTracking.Recenter(); command does nothing for Vive case.

    It's really amazing this has not been widely addressed. (How can you make Vive apps or kiosks elsewise?)

    Thank you so much - lifesaver.
     
    Last edited: Sep 22, 2016
  7. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Great to hear that it works, I haven't tried it yet. :)
     
    Fattie likes this.
  8. MeOwOHa

    MeOwOHa

    Joined:
    Sep 29, 2016
    Posts:
    1
    Can it works in 5.2.2?
     
  9. Fattie

    Fattie

    Joined:
    Jul 5, 2012
    Posts:
    375
    No, you must download 5.4.1p2 - or whatever is the latest patch as you are reading this in the future. 5.2 won't work.


    Here's an example of us doing it...


    Code (CSharp):
    1.     private void DoRecenterHeadsetOnThisStation()
    2.         {
    3.         // essential to FIRST sit the vehicle and/or humanoid
    4.         // totally straight and looking forward:
    5.         // in this example the humanoid does not move at all,
    6.         // so simply set the vehicle absolutely square:
    7.  
    8.         Quaternion temp = littleTrainTransform.rotation;
    9.         littleTrainTransform.rotation = Quaternion.identity;
    10.  
    11.         // useless: UnityEngine.VR.InputTracking.Recenter();
    12.  
    13.         // some say to skip a frame here. works for us without.
    14.  
    15.         Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    16.         // WTT Todd-Wasson Unity Forums
    17.         Valve.VR.OpenVR.Compositor.SetTrackingSpace(
    18.                 Valve.VR.ETrackingUniverseOrigin.TrackingUniverseSeated);
    19.         // WTT Todd-Wasson Unity Forums
    20.  
    21.         // some say to skip a frame here. works for us without.
    22.  
    23.         // the point of view (pov) VR camera of course must sit in an empty Transform
    24.         // (called povHandler in this app)
    25.         // it's a basic of VR in Unity that you can't move the camera itself, only a holder.
    26.  
    27.         // AFTER the above lines of code, simply shift that povHandler to the
    28.         // bridge of the nose of the humanoid model.
    29.         // (FWIW we find it's actually best about 8 inches in front of the bridge of the nose)
    30.         // (the call FixOrReFixNow simply moves povHandler to that point)
    31.         povHandler.FixOrReFixNow();
    32.  
    33.         littleTrainTransform.rotation = temp;
    34.  
    35.         // in our system, all of the above works perfectly within a frame,
    36.         // and the user does not experience any flickering or other woes.
    37.         // the user just "moves to" the correct position perfectly, phew.
    38.  
    39.         // in this example, flash an indication that you have been centered...
    40.         StationUX su = FindObjectOfType<StationUX>();
    41.         if (su) su.DoXHairs();
    42.         }
     
    Last edited: Sep 29, 2016
    Todd-Wasson likes this.
  10. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Thanks, Fattie! That works for me too (5.5.1p4 although I don't have a Vive to test it on to be 100% sure).

    Here's what I'm doing now with Oculus and OpenVR libraries working together to support both Vive and Oculus. In player settings, Oculus is in the SDK list on top so it will use that if Oculus is found (it goes in order from top to bottom so make sure Oculus is on top if you want Oculus to use that SDK instead of OpenVR. This was recommended by Unity.). If Oculus is not there it'll then check OpenVR and use that.

    Then I just have a simple class with a static function in it like this:

    Code (csharp):
    1. public static void RecenterVR()
    2.     {
    3.         if (VRSettings.loadedDeviceName == "Oculus")
    4.         {
    5.             print("Reset VRSettings.loadedDeviceName == Oculus");
    6.             UnityEngine.VR.InputTracking.Recenter();
    7.         }
    8.  
    9.         if (VRSettings.loadedDeviceName == "OpenVR")
    10.         {
    11.             print("Reset VRSettings.loadedDeviceName == OpenVR");
    12.             Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    13.          
    14.             Valve.VR.OpenVR.Compositor.SetTrackingSpace(Valve.VR.ETrackingUniverseOrigin.TrackingUniverseSeated);
    15.         }
    16.     }
    So anywhere where the camera is getting reset, I just call ThisClass.RecenterVR(). It figures out from VRSettings.loadedDeviceName whether it's using the OpenVR or Oculus SDK, then calls the appropriate functions, and if it's not VR at all (mine runs in VR and non-VR) it will do nothing.

    This is for a sitting game, so for standing it'll be a little different on the OpenVR side probably.
     
    arufolo likes this.
  11. Shovancj

    Shovancj

    Joined:
    Dec 21, 2011
    Posts:
    16
    Unity v- 5.5.0p1
    I get a NULL Ref on Valve.VR.OpenVR.ResetSeatedZeroPose();

    I have the [SteamVR] prefab in the scene and is set to tracking universal seated.

    Player settings just has OpenVR in the list.

    Any Ideas? Am I missing something?
     
  12. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Don't use a prefab. Unity has native support now.
     
  13. Shovancj

    Shovancj

    Joined:
    Dec 21, 2011
    Posts:
    16
    Removed the prefab.

    called UnityEngine.VR.InputTracking.Recenter(); Null Ref

    called Valve.VR.OpenVR.ResetSeatedZeroPose(); Null Ref

    What should i be calling to center the head pos?
     
  14. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    6,189
    Have you debugged to see what is null?
     
  15. Shovancj

    Shovancj

    Joined:
    Dec 21, 2011
    Posts:
    16
    Sorry, I must have run the wrong build for the test on the UnityEngine.VR.InputTracking.Recenter(). It does not Null Ref, although the pos the camera before and after the call is the same.

    Also, After rebuilding again with the Valve.VR.OpenVR.System.ResetSeatedZeroPose() I no longer run into a Null Ref.

    Code (CSharp):
    1. Debug.Log("gameobject cam obj pos = " + cam.transform.position.ToString());
    2.             UnityEngine.VR.InputTracking.Recenter();
    3.             //Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    4.             //SteamVR.instance.hmd.ResetSeatedZeroPose();
    5.             Debug.Log("gameobject cam obj pos after = " + cam.transform.position.ToString());
    This prints same pos before and after the Recenter Call

    Code (CSharp):
    1. Debug.Log("gameobject cam obj pos = " + cam.transform.position.ToString());
    2.             //UnityEngine.VR.InputTracking.Recenter();
    3.             Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    4.             //SteamVR.instance.hmd.ResetSeatedZeroPose();
    5.             Debug.Log("gameobject cam obj pos after = " + cam.transform.position.ToString());
    This prints same pos before and after the ResetSeatedZeroPose Call

    Code (CSharp):
    1. Debug.Log("gameobject cam obj pos = " + cam.transform.position.ToString());
    2.             //UnityEngine.VR.InputTracking.Recenter();
    3.             //Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    4.             SteamVR.instance.hmd.ResetSeatedZeroPose();
    5.             Debug.Log("gameobject cam obj pos after = " + cam.transform.position.ToString());
    This gives me an Interface not found with this log

    Interface Not Found (105)
    UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object)
    UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
    UnityEngine.Logger:Log(LogType, Object)
    UnityEngine.Debug:Log(Object)
    SteamVR:ReportError(EVRInitError) (at C:\Users\Curtis\Desktop\test\Assets\SteamVR\Scripts\SteamVR.cs:116)
    SteamVR:CreateInstance() (at C:\Users\Curtis\Desktop\test\Assets\SteamVR\Scripts\SteamVR.cs:80)
    SteamVR:get_instance() (at C:\Users\Curtis\Desktop\test\Assets\SteamVR\Scripts\SteamVR.cs:48)
    test:Update() (at C:\Users\Curtis\Desktop\test\Assets\test.cs:25)

    (Filename: C:/Users/Curtis/Desktop/test/Assets/SteamVR/Scripts/SteamVR.cs Line: 116)

    NullReferenceException: Object reference not set to an instance of an object
    at test.Update () [0x0005e] in C:\Users\Curtis\Desktop\test\Assets\test.cs:25


    Thanks for your help!
     
  16. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Are you trying to use the SteamVR plugin? Don't do that, Unity has native support now.

    My code:
    Code (csharp):
    1.  
    2.  Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    3.  
    Yours:
    Code (csharp):
    1.  
    2. SteamVR.instance.hmd.ResetSeatedZeroPose();
    3.  
     
  17. Radiangames2

    Radiangames2

    Joined:
    Aug 22, 2012
    Posts:
    31
    Can you explain what you mean by native support, because I'm not seeing it. Is there a Valve namespace in UnityEngine that I'm missing? I don't have any plug-ins loaded and I'm trying to get Unity to reset the seated position. Where is this call coming from?

    We have our game running in OpenVR, but don't see any way to access OpenVR in script.

    I'm on Unity 5.5.2p2, the latest patch release available as of earlier today. (March 16th, 2017)

    Thanks!
     
  18. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    Native support means you don't need the SteamVR plugin, the OpenVR stuff is all built into Unity. It's like Oculus now where you just use a regular Unity camera without a special camera rig.

    You can either call the function like this:
    Code (csharp):
    1.  
    2. Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    3.  

    Or use a using like this:
    Code (csharp):
    1.  
    2. using Valve.VR.OpenVR;
    3. //Later in some function:
    4. System.ResetSeatedZeroPose();
    5.  
    Don't call functions that have "SteamVR" in them. When you do that you're using the SteamVR plugin instead of the built in Valve.VR stuff.
     
  19. Radiangames2

    Radiangames2

    Joined:
    Aug 22, 2012
    Posts:
    31
    Todd: I'm sorry, but Valve does not exist in the UnityEngine namespace anywhere. You must have a plugin/asset installed that has the Valve namespace.

    Did a full search on the Unity documentation, and examined the full namespace, and Valve does not exist in either.

    I would be happy to use the Valve.VR namespace if I could find it. Keep in mind I *do not* have the OpenVR SDK installed either.
     
  20. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,061
    It's not in the UnityEngine namespace, Valve is it's own namespace.

    Sorry, if it's not showing up for you I don't know what else to say. I don't have the OpenVR SDK installed either. I don't recall doing anything special, as far as I know I went from an older version of Unity to a newer one and suddenly it was there.
     
  21. FlightCrazed

    FlightCrazed

    Joined:
    Aug 1, 2014
    Posts:
    54
    Todd's solution almost worked for me. But here's what I had to do to finally make it to work(unity 5.6.x):

    Code (CSharp):
    1.     private void Start()
    2.     {
    3.         _steamRend = FindObjectOfType<SteamVR_Render>();
    4.     }
    5.  
    6. void ResetToSeatedPose(SteamVR_Render _steamRend)
    7.     {
    8.         _steamRend.trackingSpace = Valve.VR.ETrackingUniverseOrigin.TrackingUniverseSeated;
    9.         Valve.VR.OpenVR.System.ResetSeatedZeroPose();
    10.     }
    11.     void ResetToStandingPose(SteamVR_Render _steamRend)
    12.     {
    13.         _steamRend.trackingSpace = Valve.VR.ETrackingUniverseOrigin.TrackingUniverseStanding;
    14.  
    15.     }

    I do also I have a question. Is it possible to, if so how to, re-orient HMD when standing (to PlayArea.forward)? What I mean is, is there a method like "ResetSeatedZeroPose()" for standing?
     
    Todd-Wasson likes this.
  22. Vivek-Savsaiya

    Vivek-Savsaiya

    Joined:
    Jan 17, 2015
    Posts:
    4
    Reposition steam controller parent according eye/head to setup on origin, it's works for me.

    Code (CSharp):
    1.  
    2.     private  Transform steamCam;
    3.     private  Transform steamController;
    4.  
    5.     void Start()
    6.     {
    7.         steamCam = FindObjectOfType<SteamVR_Camera>().gameObject.transform;
    8.         steamController = FindObjectOfType<SteamVR_ControllerManager>().transform;
    9.         steamController.position = new Vector3( -(steamCam.position.x), 0, -(steamCam.position.z));
    10.     }
     
  23. RyuHayaboosa

    RyuHayaboosa

    Joined:
    Mar 8, 2015
    Posts:
    5
    If anyone wants to do this without importing the SteamVR package you can now use

    XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
    InputTracking.Recenter();

    in 2017.2.0f3.
     
    Paalo, Innovine, DarkDogma3D and 2 others like this.
  24. gstarch

    gstarch

    Joined:
    Mar 21, 2015
    Posts:
    4
    I spent a lot of time looking for a answer on this. Tried all of the options on this thread without success. Looked like several of the SteamVR/Valve and native solutions stopped working after a recent update. Eventually wrote this script which took care of it to my liking.

    This script will allow a reset of the SteamVR camera rig to align with a transform representing the desired head position in the scene. Attach to any GameObject in the scene. Useful for seated experiences like cockpits.

    Code (CSharp):
    1. public class ResetSeatedPosition : MonoBehaviour {
    2.     [Tooltip("Desired head position of player when seated")]
    3.     public Transform desiredHeadPosition;
    4.     private Transform steamCamera;
    5.     private Transform steamController;
    6.  
    7.     // Update is called once per frame
    8.     void Update () {
    9.  
    10.         if (Input.GetKeyDown(KeyCode.Space))
    11.         {
    12.             if (desiredHeadPosition != null)
    13.             {
    14.                 ResetSeatedPos(desiredHeadPosition);
    15.             }
    16.             else
    17.             {
    18.                 Debug.Log("Target Transform required. Assign in inspector.");
    19.             }
    20.          
    21.         }
    22.     }
    23.  
    24.     private void ResetSeatedPos(Transform desiredHeadPos){
    25.  
    26.         //find VR Camera and CameraRig transforms in scene
    27.         steamCamera = FindObjectOfType<SteamVR_Camera>().gameObject.transform;    
    28.         steamController = FindObjectOfType<SteamVR_ControllerManager>().transform;
    29.  
    30.         if ((steamCamera != null) && (steamController != null))
    31.             {
    32.             //{first rotation}
    33.                 //get current head heading in scene
    34.                 //(y-only, to avoid tilting the floor)
    35.                 float offsetAngle = steamCamera.rotation.eulerAngles.y;
    36.                 //now rotate CameraRig in opposite direction to compensate
    37.                 steamController.Rotate(0f, -offsetAngle, 0f);
    38.  
    39.             //{now position}
    40.                 //calculate postional offset between CameraRig and Camera
    41.                 Vector3 offsetPos = steamCamera.position - steamController.position;
    42.                 //reposition CameraRig to desired position minus offset
    43.                 steamController.position = (desiredHeadPos.position - offsetPos);
    44.  
    45.                 Debug.Log("Seat recentered!");
    46.             }
    47.         else
    48.             {
    49.                 Debug.Log("Error: SteamVR objects not found!");
    50.             }
    51.     }
    52. }
    53.  
    Turned out to be simpler than I expected. Hope it can save someone else the time!

    Cheers,

    Gerry

    PS: Running Unity 2017.2
     
  25. Pingly

    Pingly

    Joined:
    Jun 14, 2015
    Posts:
    9
    Thanks so much. Just tried my project on Vive for the first time and I'm standing on my head.

    Thanks for the code.
     
  26. DarkDogma3D

    DarkDogma3D

    Joined:
    Mar 29, 2016
    Posts:
    5
    Thanks a lot! it worked for me with a vive visor and an xbox one controller running unity 2017.3
     
  27. PiFLYON

    PiFLYON

    Joined:
    Aug 1, 2016
    Posts:
    4
    Thank you ryuhayaboosa, the SetTrackingSpaceType solved the problem of the height of the camera.
    For newbies like me, add "UnityEngine.Xr." before.
     
    FlightCrazed likes this.
  28. ElizaW004

    ElizaW004

    Joined:
    May 21, 2018
    Posts:
    4
    Hi
    i have Quary - please if anyone can resolve me this!
    here i posted my question - https://forum.unity.com/threads/new-apple-animoji.539965/

    im making Animoji like in iphoneX - working in Xcode only not in uniyt.
    can anyone resolve me this how to make animoji like in iphone X.
    is ther any role of uniyt3d or just Xcode?
    and is there anything in Export files from 3ds Max like .Dae or .FBX or anyother formate.??
     
  29. Paalo

    Paalo

    Joined:
    Jan 20, 2016
    Posts:
    3
    The solution @gstarch suggested is the way to go. It works both for Room Scale & Seated Experiences.

    Some things to remember though:
    • An important change is that the
      SteamVR_ControllerManager
      -script isn't attached to the
      [CameraRig]
      -prefab coming with the SteamVR-plugin anymore (in SteamVR version 1.2.3 and up).
      • This also means that the variable
        steamController
        is supposed to be set to the
        [CameraRig]
        -prefab coming with the SteamVR-plugin.
    • How Unity.XR works:
      • The function
        UnityEngine.XR.InputTracking.Recenter();
        ONLY works for Seated/Standing Experiences, ie. it won't do anything if you have set up a Room Scale-experience.
    Here's our modified version of @gstarch's solution. Works with
    Unity 2018.3.0b11
    &
    SteamVR Version 1.2.3


    Hope this helps someone!

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayAreaController : MonoBehaviour
    4. {
    5.     [Tooltip("Desired head position of player when seated")]
    6.     public Transform desiredHeadPosition;
    7.  
    8.     //Assign these variables in the inspector, or find them some other way (eg. in Start() )
    9.     public Transform steamCamera;
    10.     public Transform cameraRig;
    11.  
    12.     private void Update()
    13.     {
    14.         if (Input.GetKeyDown(KeyCode.Space))
    15.         {
    16.             if (desiredHeadPosition != null)
    17.             {
    18.                 ResetSeatedPos(desiredHeadPosition);
    19.             }
    20.             else
    21.             {
    22.                 Debug.LogError("Target Transform required. Assign in inspector.", gameObject);
    23.             }
    24.         }
    25.     }
    26.  
    27.     private void ResetSeatedPos(Transform desiredHeadPos)
    28.     {
    29.         if ((steamCamera != null) && (cameraRig != null))
    30.         {
    31.             //ROTATION
    32.             // Get current head heading in scene (y-only, to avoid tilting the floor)
    33.             float offsetAngle = steamCamera.rotation.eulerAngles.y;
    34.             // Now rotate CameraRig in opposite direction to compensate
    35.             cameraRig.Rotate(0f, -offsetAngle, 0f);
    36.  
    37.             //POSITION
    38.             // Calculate postional offset between CameraRig and Camera
    39.             Vector3 offsetPos = steamCamera.position - cameraRig.position;
    40.             // Reposition CameraRig to desired position minus offset
    41.             cameraRig.position = (desiredHeadPos.position - offsetPos);
    42.  
    43.             Debug.Log("Seat recentered!");
    44.         }
    45.         else
    46.         {
    47.             Debug.Log("Error: SteamVR objects not found!");
    48.         }
    49.     }
    50. }