MotionController Input for multi player

Hi All,

I am trying to change my setup to allow for two players where each uses motion controllers(hydras for now), using the now standard component.

But I don’t seem to be able to get each player have their own input.
I have tried setting the ‘Player Index’ to 0 and 1 depending on player game instance but that doesn’t seem to do it.
The input still flows to both clients’ player Pawns.

I’,m sure this is simple but I can’t seem to find the answer. Anyone?

Cheers

Try using an authority switch A Crash Course in Blueprint Replication - Unreal Engine before the input gets forwarded. It would be great if someone with multiplayer vive/touch could let us know how it is handled there.

Hi Getnamo,

hmm…in this particular setup I just use some cubes to visualize my hands, so there is no actual blueprint or c++ code to do anything further.
Like so


So here there’s no way to add a authority switch right?

I will still try making something now to try what you suggest…
(as I do more elsewhere)

I have been trying to find a fix for this for a while now. Last week during Sam and Wes’ VR stream they were talking about how 4.11 has this fixed on the code side and they provided the code to fix it.



bool UMotionControllerComponent::PollControllerState(FVector& Position, FRotator& Orientation)
{
	if (IsInGameThread())
	{
		// Cache state from the game thread for use on the render thread
		const APlayerController* Actor = Cast<APlayerController>(GetOwner());
		bHasAuthority = !Actor || Actor->IsLocalPlayerController();
	}


Also if you watch that twitch stream they talk about how we could possibly implement this code into 4.10 (right after Wes finished the teleport tutorial). I’m not particularly good with coding so I couldnt get it to build properly. If anyone tries this and makes it work can you please post back your process.

I just tried to do this but the problem is still the same. The input flows to both Player1 and Player2 pawns.
I tried using both ‘Authority’ and ‘Remote’.
It just makes the MC’s work or not in one or the other game instance window.

Wes was saying on the stream that there is no Blueprint way of doing it so that’s why its got to be implemented to the motioncontroller code.

Hmm…yes I am also trying right now doing it with code instead.

I added a c++ component class inheriting from the standard motion controller.
But in Visual Studio the .cpp and .h are almost blank so I am not sure what and how to add that bit you posted.

They seemed to say I should be able to just do add code, and not need the full Engine source build, right?

Where did you get that code snippet?

It would be incredibly helpful if anyone could tell us how to do this!?

Cheers

After skimming over this quickly, it appears to be an engine fix. So your best bet is to wait for 4.11 as there isn’t a good way to fix this for plugins that isn’t a workaround.
If you do want a workaround though, one way would be to get the positions manually (e.g. hydra events) and putting the authority check there before affecting your output/etc, but then you’re not using the motion controller abstraction.

Relevant code changes (line 78):


bool UMotionControllerComponent::PollControllerState(FVector& Position, FRotator& Orientation)

in

https://github.com/EpicGames/UnrealEngine/blob/master/Engine/Source/Runtime/HeadMountedDisplay/Private/MotionControllerComponent.cpp

@getnamo

On the thread for that twitch stream Wes from Unreal says,

At the moment I have a setup probably something like you suggest, I am using intermediate objects for the tracked motion and have a stop-start filter setup that I can hotkey switch between Player1 and Player2.
It is not a good solution though and I am afraid that it will cause extra confusion when setting up the multiplayer and replication, if I forget to add this properly at the right places or make any mistakes in my switch setups.

Hoping for a proper in engine solution.

Cheers

Hello,
I use 4.11.1 version and i still have the same problem.
I have a replicated variable which contains the transformations of the right Motion Controller.
Only Server modify this variable
But, server seems to use only the tranforms of motion controller of the player which is server…

I wonder if motion controllers aren’t “nativelty” replicated when child of a BP which is replicated, and if i have to use “Player index” to obtain the good result ?
I found that “replicate movement” has an action on these components (not only movement component).

Could you help me ?

I had to add network support for motion controllers on a project and I have not seen any native implementation for replication. Ended up writing it from scratch.
So this shouldn’t be the cause of your issue.

The replication seems to be automatic… when activating replication on the pawn actor.
It’s a good point… But the bad point is that it uses the Motion controllers of the first pawn… Player Index, a solution ? Maybe, but what number ? Where can i find it ?

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