Motion controllers and networking

I’m going to bump this one too. I’m also trying to get replicated motion controllers working based on the VR template, with about the same amount of luck.

Yes, that’s true only for the server, but it’s the MyPawn->IsLocallyControlled() that’s the important part here.

Also, I’ve discovered a bit of a flaw in this that might explain why some people are having such a tough time, especially when coming at it from the VR Template project. The current code is as follows:


const AActor* MyOwner = GetOwner();
const APawn* MyPawn = Cast<APawn>(MyOwner);
bHasAuthority = MyPawn ? MyPawn->IsLocallyControlled() : (MyOwner->Role == ENetRole::ROLE_Authority);

The problem comes in when casting MyOwner to a pawn. In the case of the VR Template, the owner of the motion controller component is BP_MotionController, not the player pawn. This means MyPawn will return null and we’ll fall back to the server having authority. I changed the code to this:


const AActor* MyOwner = GetOwner();
while( MyOwner && MyOwner->GetOwner() != nullptr )
{
    MyOwner = MyOwner->GetOwner();
}
const APawn* MyPawn = Cast<APawn>(MyOwner);
bHasAuthority = MyPawn ? MyPawn->IsLocallyControlled() : (MyOwner->Role == ENetRole::ROLE_Authority);

This changes the code to get the outermost owner, which will be the pawn (at least in the case of the VR Template).

At this point, I’ve finally got the motion controllers only tracking for the local player. I just need to get the positions replicating and I should be good to go.

Looking for a solution that is all c++. Best we have so far is the Server Replicating on the Client but not the other way around. Anyone have a solution or steps that they could hint at?

hi,
Im testing this out and notice that there is lag, even in the editor VR player. i assume its the tick. Is there a way to speed this up?

Issue persists in 4.15

if just motion controller positions , you can use UDP messaging to broadcast to other player ,without using the replication.

[USER=“500705”]stag beetle[/USER], How would you insure the position was for the same pawn on the server, replication seems to do it for you?

Anyway, 4.17 has the same problem mirroring controllers, is this still an issue in 4.19?

Hi guys. I got the same issue and I managed to fix it in quite simple way.
First I did some research and I found many threads about the same problem. I post them at the end of the post so you can make some additional reading if you want to.

So in UMotionControllerComponent inside the PollControllerState method there is an authority check…


  
if (IsInGameThread())
{
     // Cache state from the game thread for use on the render thread
     const AActor* MyOwner = GetOwner();
     const APawn* MyPawn = Cast<APawn>(MyOwner);
     bHasAuthority = MyPawn ? MyPawn->IsLocallyControlled() : (MyOwner->Role == ENetRole::ROLE_Authority);
}

if (bHasAuthority)
    {
        TArray<IMotionController*> MotionControllers = IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>(IMotionController::GetModularFeatureName());
        for (auto MotionController : MotionControllers)
        {.....


Authority check in here is not enough because what we do later is telling the engine to get all motion controllers out there and process them. So if one of them got authority you still update them all.
PollControllerState is a private method so you cannot edit definition of that method. So instead I wrote this piece of code inside the TickComponent in my UMotionControllerComponent derived class



void UNetworkMotionControllerComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    const AActor* MyOwner = GetOwner();
    const APawn* MyPawn = Cast<APawn>(MyOwner);
    bHasAuthority = MyPawn ? MyPawn->IsLocallyControlled() : throw;
    if (bHasAuthority == false)
    {
        SetAssociatedPlayerIndex(-1);
// this line is where we tell the engine to not to use this controller. PlayerIndex variable is used differently in platform specific places. eg. SteamVR uses some 2 dimensional array to store the controllers and then only checks if they are smaller than the max value so it can be a better solution to set it to maximum value of int instead. You have to check it up with your platform. (-1 works well with oculus rift and htc vive)
    }

    if (bIsActive&&PlayerIndex == 0)
    {
        FVector Position;
        FRotator Orientation;
        float WorldToMeters = GetWorld() ? GetWorld()->GetWorldSettings()->WorldToMeters : 100.0f;
        const bool bNewTrackedState = PollControllerState(Position, Orientation, WorldToMeters);
        if (bNewTrackedState)
        {
            Server_SetRelativeLocationAndRotation(Position, Orientation);
            //SetRelativeLocationAndRotation(Position, Orientation);
        }
//rest of the default motioncontrollercomponent's code


So basically you have to do those things:

  1. set PlayerIndex != 0 on the controllers that should’t get the data from you motion controller.
  2. implement the function that will set the position and rotation. It have to be done on server so the other clients can see it. I copied the code from USceneComponent::SetRelativeLocationAndRotation() and it woks like a charm.

Please keep in mind that this is the working solution but its like alpha alpha version. I’m sure I’ll try to optimize this so I don’t have to do all those casting inside of a tick function and get rid of the throwing exceptions when there is no Pawn. Do not use this as ready to go solution in your projects. I posted this only as a reference so you can get on going with your projects if you stucked.

Links to read if you want to get more information:

https://forums.unrealengine.com/development-discussion/vr-ar-development/79167-motion-controllers-and-networking
https://forums.unrealengine.com/development-discussion/vr-ar-development/73125-motioncontroller-input-for-multi-player

https://forums.unrealengine.com/development-discussion/vr-ar-development/79167-motion-controllers-and-networking?107140-Motion-controllers-and-networking=
VR: Cameras, Multiplayer, Tips & Tricks | Live Training | Unreal Engine - YouTube at 14:35
and the thread about this livestream
Training Stream - Sam and Wes' VR Stream: Cameras, Multiplayer, Tips and Tricks! - Live from Epic HQ - Announcements - Unreal Engine Forums

I have an open source full implementation of replicating the controllers with a set Htz and smoothing already if it saves you some time.

Most of it is in the TickComponent function of my controller subclass.
https://bitbucket.org//vre…rComponent.cpp

The struct that is uses for the actual replication is in another header file, it has a lot of optimizations for the replicated data.

Hi, I need some help on this subject, can’t quite understand the blueprint workaround, can someone assist me? =(

Hello,

I’m trying to create local LAN VR Multiplayer where both players are using VR Headset (VIVE)

I’m using the VR Template From EPIC

First of all, I want to ask if the motion controller template is capable of LAN Multiplayer straight out of the box? Is it normal to face such problems like these I will describe below?

  1. The problem is when the client joins the Host, the host doesn’t see the client motion controller hands.
    The client can call RPC’s and both of the players can see the result.

  2. Also, the Client can’t teleport using the navmesh, but the server can.

  3. On Spawn the Client receives an additional pair of skeletal hands attached to his left hand.

Does anybody have a clue how I can fix that?

​​​​​​​Have you found a solution to 3)?

For 2) you have to go into the project settings and there into the nav system tab and there set “allow client navigation”.
For 1) I am new too, but the motion controller locations and orientations are imo entirely client side (see this thread for a solution).

The VR Template is just for singleplayer (speaking as of version 4.24).

As of engine version 4.24 there does not seem to be a “Get Hand Position and Orientation” node anymore. Anyone knows alternative nodes?

But how do you know which hand is where without Motion controllers Components?I wanted to try but I had no idea.