Okay so here is your cookie cutter solution for if you don’t want to have the whole mess of the Steam API in your project creating it’s inputs and it’s key files or whatever it does. I’ve cut the Steam API for loading levels only down into two files that you can find here:
https://tinyurl.com/y57vo42g - Open VR API
https://tinyurl.com/yy4l4p3v - SteamVR_LoadLevel simplified and with SteamVR and SteamVR_Settings mashed into it, with modded code so that it just displays a black screen over the compositor so you never see the compositor.
Please test this and see if this works for you, it should just have it cut to black instead of showing the compositor.
You still have to use this of course:
SteamVR_LoadLevel(string sceneName);
Test it like this:
using Valve.VR;
using UnityEngine;
using System.Collections;
public class switchscene : MonoBehaviour
{
IEnumerator Start()
{
yield return new WaitForSeconds(1);
Debug.Log("3");
yield return new WaitForSeconds(1);
Debug.Log("2");
yield return new WaitForSeconds(1);
Debug.Log("1");
yield return new WaitForSeconds(1);
Debug.Log("LoadLevel");
//Remember that this is also async:
SteamVR_LoadLevel.Begin("MY SCENE NAME GOES HERE",false,0f,0, 0, 0, 1);
}
}
That’s for loading levels…well…unfortunately, I don’t think there is a solution for if your application drops in frames. I’m going to see if I can just detect it and then intentionally myself kick it into the compositor before it can automatically do it so that I can create the overlay myself. Otherwise, I guess you just can’t have fps drops no matter what, everything must absolutely be completely asynchronous as much as possible.
However…there MAY be a way thanks to this little number included in the Unity API:
XRStats.TryGetDroppedFrameCount
I think I read that Steam VR will kick you into the compositor when it detects just 10 dropped frames. It might be possible to pre-maturely kick it into the compositor before those 10 dropped frames and in that way set up the black screen ahead of time…but I doubt it’s possible to be honest because Steam VR does it automatically. Not sure.
I’m really hoping as I test it that the OpenVR API file included in the Steam API doesn’t actually override Unity OpenVR’s input settings, as literally when I made my project OpenVR compatible, set up my inputs, everything was working until I imported the Steam API in with all it’s extra mess. Will report back here to see if that’s the case.
EDIT: The Steam VR Skybox is supposed to be able to do it but it doesn’t seem to work. Here’s the code cut down. I created a texture 256x256, named it “BLACK.png” and put it inside a folder I named ‘Resources/System/’. I also made it uncompressed and turned off mipmaps.
Texture blackTex = (Texture)Resources.Load("System/BLACK");
var compositor = OpenVR.Compositor;
if (compositor != null)
{
var handles = new Texture[] {
blackTex,
blackTex,
blackTex,
blackTex,
blackTex,
blackTex
};
var textures = new Texture_t[6];
for (int i = 0; i < 6; i++)
{
textures[i].handle = (handles[i] != null) ? handles[i].GetNativeTexturePtr() : System.IntPtr.Zero;
textures[i].eType = SteamVR.instance.textureType;
textures[i].eColorSpace = EColorSpace.Auto;
}
var error = compositor.SetSkyboxOverride(textures);
if (error != EVRCompositorError.None)
{
Debug.LogError("<b>[SteamVR]</b> Failed to set skybox override with error: " + error);
if (error == EVRCompositorError.TextureIsOnWrongDevice)
Debug.Log("<b>[SteamVR]</b> Set your graphics driver to use the same video card as the headset is plugged into for Unity.");
else if (error == EVRCompositorError.TextureUsesUnsupportedFormat)
Debug.Log("<b>[SteamVR]</b> Ensure skybox textures are not compressed and have no mipmaps.");
}
}
The only other thing I could suggest and the obvious thing like you’ve suggested is to just make everything completely and utterly asynchronous. I have a pretty bulky project so it’s a complicated issue, but for anyone designing a VR game that’s not a port it’s probably not gonna be such a big deal to design their project around being asynchronous to begin with.
The problem is, SceneManager.LoadAsync is dropping frames for me so there’s no way like you said I can’t use the Steam VR plugin. In my humble opinion Steam should seriously just have an option for developers like a bool that just shows black for the compositor. Same thing with the OVR plugin. Also, there need to be minimalistic versions of these assets without all the added extra stuff that some developers prefer to do themselves. We’re programmers, having less drag and drop can actually make development much faster.
Personally for porting my own project, I make use of Resources.Load all over the place and I think in like 50,000 lines of code only use an IEnumerator like once. There are two places in particular where it lags, so it’s gonna be a pain in the ass getting it all async because I have to make more states.
For anyone reading this be warned about VR development, design async.
EDIT: And here’s my final update to this…basically, I pinned down the program kicking me into the compositor to a single line of code, and it’s literally just pouring one structure/class into another. It’s not Resources.Load and there’s no way to actually make the process asynchronous. Great…I’m gonna try writing to valve about it, for the time being it just seems like data heavy games will just have this happen to them with no way out.