While working on VR Engine, I needed to detect what kind of controller the player is using (e.g. Index, Vive, Oculus) and surprisingly there doesn’t seem to be a native function for it so I went out to then internet and searched for a way but nothing came up.
My first idea was to get the device name of the motion controllers but that just reports as “SteamVR” which doesn’t really help.
After digging around, SteamVR apparently doesn’t expose what devices are actually connected.
While messing around with some of the settings in the motion controller component I noticed it has a setting to display the device model which corresponds with the player is using or a custom mesh. What if we can detect the name of the model its showing?
After testing with some code, I can finally detect the controller by using customDisplayMesh->GetFName()
!
Here is a simple function example of my idea:
UENUM(BlueprintType)
enum class EMotionControllerType : uint8
{
ValveIndex UMETA(DisplayName = "Valve Index"),
HTCVive UMETA(DisplayName = "HTC Vive"),
OculusTouch UMETA(DisplayName = "Oculus"),
NoController UMETA(DisplayName = "No Controller"), // Unlikely this will get triggered
Unknown UMETA(DisplayName = "Unknown")
};
EMotionControllerType ABaseMotionController::GetControllerType()
{
FString ControllerTypeString;
UMotionControllerComponent* MC = CreateDefaultSubobject(
TEXT("MotionController_Detect"));
MC->bDisplayDeviceModel = true;if (IsValid(MC->CustomDisplayMesh)) // Returns Null if no controllers are presentControllerTypeString = MC->CustomDisplayMesh->GetFName().ToString().ToLower();
MC->DestroyComponent();
if (ControllerTypeString.IsEmpty())
{
UE_LOG(LogBaseMotionController, Warning, TEXT("WARNING: I don't think you have your controllers switched on."));
return EMotionControllerType::NoController;
}if (ControllerTypeString.Contains("OculusTouch", ESearchCase::IgnoreCase))
{
UE_LOG(LogBaseMotionController, Verbose, TEXT("INFO: I think your using the Oculus Touch controllers."));
return EMotionControllerType::OculusTouch;
}if (ControllerTypeString.Contains("indexcontroller", ESearchCase::IgnoreCase))
{
UE_LOG(LogBaseMotionController, Verbose, TEXT("INFO: I think your using the Valve Index controllers."));
return EMotionControllerType::ValveIndex;
}if (ControllerTypeString.Contains("MicrosoftMixedReality", ESearchCase::IgnoreCase))
{
UE_LOG(LogBaseMotionController, Verbose, TEXT("INFO: I think your using the Microsoft Mixed Reality controllers."));
return EMotionControllerType::WindowsMixedReality;
}if (ControllerTypeString.Contains("HTCVive", ESearchCase::IgnoreCase))
{
UE_LOG(LogBaseMotionController, Verbose, TEXT("INFO: I think your using the HTC Vive controllers."));
return EMotionControllerType::HTCVive;
}UE_LOG(LogBaseMotionController, Warning, TEXT("WARNING: I can't seem to detect what controller your using, try manually setting ControllerType."));
return EMotionControllerType::Unknown;};
Basically when this function is called it will spawn a controller component, make it display the model, get the name of the model being used and then destroy itself.
This is the best way I can come up with at the time of writing this.