[BUG] UE 4.15.3, Win10, SteamVR: Incorrect Behavior of EnableHMD and IsHeadMountedDisplayEnabled in Packaged Game

Symptoms:

In packaged builds, testing with HTC Vive, IsHeadMountedDisplayEnabled and enableHMD always return false regardless of whether an HMD is already enabled or was successfully enabled.

This is an issue since it hinders development of games that are meant for both VR and non-VR mode. Specifically, if relying on IsHeadMountedDisplayEnabled or enableHMD’s return values to execute a VR or non-VR codepath, this will work in the editor by testing with PIE and VR Preview. But it will not work in the packaged build since both methods will always return false.

Possible Causes

  1. The implementation of IsHeadMountedDisplayEnabled and/or enableHMD is incorrect.
  2. The implementations are correct but the semantics are not properly documented anywhere.
  3. The implementations are correct and its’ a SteamVR issue.

Steps to Repro:

  • Create a blank C++ project.

  • Disable all VR plugins but for SteamVR.

  • Override the the project supplied C++ GameModeBase subclass’s BeginPlay, like so:

     void AHDMBugGameModeBase::BeginPlay() {
         bool hmdConnected = UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayConnected();
         bool hmdEnabled = UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled();
         FName hmdName = UHeadMountedDisplayFunctionLibrary::GetHMDDeviceName();
         bool couldEnableHMD = UHeadMountedDisplayFunctionLibrary::EnableHMD(true);
     
         UE_LOG(LogTemp, Warning, TEXT("0XFEDE: HMDBug C++: connected: %i | enabled: %i | name: %s | couldEnable: %i"),
     	hmdConnected, hmdEnabled, *hmdName.ToString(), couldEnableHMD);
     
         Super::BeginPlay();
     }
    
  • OPTIONAL: (if you want to double check in BP) Create a blueprint subclass of this game mode and implement it’s BeginPlay in a similar way:

  • Assign the BP subclass as the gamemode for a new level. So that you get both the C++ and BP code to run.
  • Test in PIE (separate window) and VR Preview mode inside the editor.
  • Build with and without Start in VR enabled and test packaged build.
  • Check the logs in all cases.

Expected:

In editor PIE:

  1. IsHeadMountedDisplayEnabled should return false
  2. enableHMD(true) should return false.

In editor VR Preview:

  1. IsHeadMountedDisplayEnabled should return true.
  2. enableHMD(true) should return true since the HMD was already enabled.

In builds:

  1. IsHeadMountedDisplayEnabled should return true if the game started in VR due to Start in VR = true.
  2. IsHeadMountedDisplayEnabled should return false if the game did not start in VR due to Start in VR = false.
  3. For either of 1 or 2, enableHMD(true) should turn on VR mode if it wasn’t already, and return true.

Actual Outcome:

In editor PIE:

  1. IsHeadMountedDisplayEnabled returns false. OK
  2. enableHMD(true) returns false. OK

In editor VR Preview:

  1. IsHeadMountedDisplayEnabled returns true. OK
  2. enableHMD(true) returns true since the HMD was already enabled. OK

In builds:

[link text][2] 1. IsHeadMountedDisplayEnabled returns false regardless of Start in VR. FAIL.
2. enableHMD(true) does turn on VR mode if it was not on, but still returns false. FAIL