cancel
Showing results for 
Search instead for 
Did you mean: 

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

viteichris
Level 4
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,









7 REPLIES 7

viteichris
Level 4
asking to ensure a pass / minimise the amount of work I do (or need to re-do 🙂 )

Raj_OOI
Level 2
@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 😞

viteichris
Level 4
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!

viteichris
Level 4
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.


Spoon420
Level 3
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.

Anoki1972
Level 3
@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?

Anoki1972
Level 3
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.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.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.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.UnPause();
}

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

}