Welcome to the Oculus Developer Forums!

Your participation on the forum is subject to the Oculus Code of Conduct.

In general, please be respectful and kind. If you violate the Oculus Code of Conduct, your access to the developer forums may be revoked at the discretion of Oculus staff.

How do I correctly implement VR focus with Unity (To pass VRC.PC.Input.1)

viteichrisviteichris Posts: 14
NerveGear
edited April 2018 in Unity Development
I'm trying to make sure our app is ready to go, but I'm not certain on what exactly I can/should do to ensure we pass this VRC:
Currently we drop into our pause menu when the app loses focus, but it seems like there's a bit more to be done:

VRC.PC.Input.1

The app must not submit frames or accept input when the user removes the HMD or opens the Universal Menu.

VR Focus

[...]
When you lose VR focus the user can no longer see your app. You should stop submitting frames, drop audio, and stop tracking input. You may also wish to save the game state so you can return the user to where they left off in your app.

Is there anything that we should be doing application side to handle this (beyond pausing gameplay elements), specifically, how can I tell Unity to stop submitting frames and tracking input?

Alternatively, is there some sort of global Unity state(?) that can be set to handle this (like UnityPlayer.pause/resume) (I'm guessing no : ) ).

Thanks,









Answers

  • viteichrisviteichris Posts: 14
    NerveGear
    asking to ensure a pass / minimise the amount of work I do (or need to re-do :) )
  • Raj_OOIRaj_OOI Posts: 6
    NerveGear
    @viteichris Did you ever solve this issue? I'm failing this test with the VRCValidator and I cannot find any answers or help, just open questions like yours with no response :(
  • viteichrisviteichris Posts: 14
    NerveGear
    I did!  Although I can’t remember how.  And I’m not at my machine right now to check.

    it might have been as simple as setting the timescale to 0 and making sure everything respected that?  I’ll check when I’m back in he office on Monday and update this answer!
  • viteichrisviteichris Posts: 14
    NerveGear
    OK, I'm back in the office and checked.  Our pause function is complicated, but essentially it boils down to:
    - Stop updating everything (timescale 0 or whatever)
    - DISABLE cameras. (this is the important one)

    The validator is checking for "app must not submit frames", so if you do `camera.enabled = false` or `camera.gameObject.SetActive(false)` then that camera will stop rendering frames and the validator won't see any!

    afaict, the validator can't really tell what's happening with input, so you just have to ensure manually that your app isn't doing anything whilst it's in this "pause" state.


  • Spoon420Spoon420 Posts: 2
    NerveGear
    Add the  following lines to your update method on OVRPlayerController
            if (OVRManager.hasInputFocus)
            {
                Time.timeScale = 1;
                CameraRig.enabled = true;
            }
            if (OVRManager.hasInputFocus == false)
            {
                Time.timeScale = 0;
                CameraRig.enabled = false;
            }

    Oculus should have this as part of their default script there is no reason I know of not too since it is required.
  • Anoki1972Anoki1972 Posts: 4
    NerveGear
    @Spoon420 How can I use your script but for the camera rig prefab only?  I am not using the OVRPlayerController in my game, I am only using the camera rig prefab. Any suggestions?
  • Anoki1972Anoki1972 Posts: 4
    NerveGear
    edited May 22
    Here a code that you attach to a game object in your scene and it works for me.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class GamePause : MonoBehaviour
    {
    public GameObject OVRCameraRig;
    public GameObject pauseMenuUIThing;
    public GameObject[] listOfObjectsToHideOnPause;

    private AudioSource[] audioSources;
    private void OnEnable()
    {
    // try to find camera rig automatically, if it's not set in the Inspector..
    if (OVRCameraRig == null)
    OVRCameraRig = GameObject.Find("OVRCameraRig");

    // this subscribes to Oculus events, so when they fire our functions get called in this script
    OVRManager.HMDUnmounted += PauseGame;
    OVRManager.HMDMounted += UnPauseGame;
    OVRManager.VrFocusLost += PauseGame;
    OVRManager.VrFocusAcquired += UnPauseGame;
    OVRManager.InputFocusLost += PauseGame;
    OVRManager.InputFocusAcquired += UnPauseGame;
    }

    private void OnDisable()
    {
    // this unsubscribes from the Oculus events when they're no longer needed (when this object is disabled etc)
    OVRManager.HMDUnmounted -= PauseGame;
    OVRManager.HMDMounted -= UnPauseGame;
    OVRManager.VrFocusLost -= PauseGame;
    OVRManager.VrFocusAcquired -= UnPauseGame;
    OVRManager.InputFocusLost -= PauseGame;
    OVRManager.InputFocusAcquired -= UnPauseGame;
    }

    private void PauseGame()
    {
    //Debug.Log("PAUSE! --------------------------------------------");
    // show menu message thing, if we have one..
    if (pauseMenuUIThing != null)
    pauseMenuUIThing.SetActive(true);

    // if we have objects to hide, let's hide them..
    for(int i=0; i< listOfObjectsToHideOnPause.Length;i++)
    {
    listOfObjectsToHideOnPause[i].SetActive(false);
    }

    // find and start all audiosources in the Scene
    AudioSource[] audioSources = GameObject.FindObjectsOfTypeAll(typeof(AudioSource)) as AudioSource[];

    for (int i = 0; i < audioSources.Length; i++)
    {
    audioSources[i].Pause();
    }

    // pause time
    Time.timeScale = 0.0f;
    }

    private void UnPauseGame()
    {
    //Debug.Log("UNPAUSE! --------------------------------------------");

    if (OVRManager.hasVrFocus && OVRManager.isHmdPresent && OVRManager.hasInputFocus)
    {
    // hide menu message thing, if we have one..
    if (pauseMenuUIThing != null)
    pauseMenuUIThing.SetActive(false);

    // if we have objects to hide, let's hide them..
    for (int i = 0; i < listOfObjectsToHideOnPause.Length; i++)
    {
    listOfObjectsToHideOnPause[i].SetActive(true);
    }

    // find and stop all audioSources in the Scene
    AudioSource[] audioSources = GameObject.FindObjectsOfTypeAll(typeof(AudioSource)) as AudioSource[];
    for (int i = 0; i < audioSources.Length; i++)
    {
    audioSources[i].UnPause();
    }

    // restart time
    Time.timeScale = 1.0f;
    }
    }

    }
Sign In or Register to comment.