Download

VR Multiplayer in 4.18 and above

Hi guys,
I’m working on a project with a dedicated Server and we upgraded the project to the Unreal version 4.18.
In 4.18 and above we noticed that there is no “GetHandPositionAndOrientation” function anymore, so we tried the Motion Controller Component, but without success.
We also tried the function “GetTrackedDevicePositionAndOrientation”, but it seems that this feature is not nearly robust.

So any ideas or tutorials how to get VR running in Multiplayer in the Unreal Engine 4.18 or higher would be great.

thanks in advance,
Janousch

Both GetHandPositionAndOrientation(…) and GetTrackedDevicePositionAndOrientation(…) work in 4.18 and 4.19, but they’re for SteamVR only. And they’re for local player of course, so you need to replicate data manually.


//build.cs

PublicDependencyModuleNames.AddRange(
    new string]
    {
        //...,
        "SteamVR",
        "HeadMountedDisplay",
        "SteamVRController"
    }
    );



// header

// local values
UPROPERTY()
FVector LocRight, LocLeft;
UPROPERTY()
FRotator RotRight, RotLeft;

// relicated values
UPROPERTY(Replicated)
FVector LocRight_Replicated, LocLeft_Replicated;
UPROPERTY(Replicated)
FRotator RotRight_Replicated, RotLeft_Replicated;

// replication event
UFUNCTION(Server, Unreliable, WithValidation)
void Server_UpdateControllers(FVector LocR, FRotator RotR, FVector LocL, FRotator RotL);
bool Server_UpdateControllers_Validate(FVector LocR, FRotator RotR, FVector LocL, FRotator RotL) { return true; };
void Server_UpdateControllers_Implementation(FVector LocR, FRotator RotR, FVector LocL, FRotator RotL)
{
    LocRight_Replicated = LocR; RotRight_Replicated = RotR;
    LocLeft_Replicated = LocL; RotLeft_Replicated = RotL;
}


// .cpp
#include "SteamVRFunctionLibrary.h"

// in tick
const float InterpSpeed = 18.f;

if (IsLocallyControlled())
{
    USteamVRFunctionLibrary::GetHandPositionAndOrientation(0, EControllerHand::Right, LocRight, RotRight);
    USteamVRFunctionLibrary::GetHandPositionAndOrientation(0, EControllerHand::Left, LocLeft, RotLeft);

    // send to server
    if (GetIsReplicated()) Server_UpdateControllers(LocRight, RotRight, LocLeft, RotLeft);
}
else
{
    // interp from relicated variables
    // right
    LocRight = FMath::VInterpTo(LocRight, LocRight_Replicated, DeltaTime, InterpSpeed);
    RotRight = FMath::RInterpTo(RotRight, RotRight_Replicated, DeltaTime, InterpSpeed);
    // left
    LocLeft = FMath::VInterpTo(LocLeft, LocLeft_Replicated, DeltaTime, InterpSpeed);
    RotLeft = FMath::RInterpTo(RotLeft, RotLeft_Replicated, DeltaTime, InterpSpeed);
}

Universal setup for Oculus and SteamVR (not tested yet with 4.19)


// header
// Motion Controller interface pointer
IMotionController* MControllers;


// .cpp
#include "Features/IModularFeatures.h"
#include "IMotionController.h"

// initialization
TArray<IMotionController*> controllers = IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>(IMotionController::GetModularFeatureName());
if (controllers.Num() > 0) MControllers = controllers[0];

// Tick:
const float WorldToMeters = 100.f;

// have to change in/after 4.19, because they're now using MotionSource (FName) instead of EControllerHand enum to identiry motion controllers and other tracked devices.
if (MControllers) {
    MControllers->GetControllerOrientationAndPosition(0, EControllerHand::Right, RotRight, LocRight, WorldToMeters);
    MControllers->GetControllerOrientationAndPosition(0, EControllerHand::Left, RotLeft, LocLeft, WorldToMeters);
}

@YuriNK thank you sooo much, you are awesome.

Super simple and effective.

Don’t you have an issues with HMD at all?
When we use dedicated server - the client just sees nothing in HMD - it shows loading forever, both Oculus/HTC. And we got just NO ideas how to solve this :frowning:

Same on 4.19. In 4.18 we discovered the HMD took 30 or 60 seconds to load on the client (even with the splash screen turned off) but in 4.19 its not showing anything anymore.