VR Hands not tracking/moving on client (Multiplayer)

I’m working on trying to make my VR game a multiplayer game. My issue is that when I’m playing on the listen server, everything works correctly. But when I join as a client, the VR hands remain on the floor and are not tracking.

I found forum posts of a similar issue where they recommend setting the PlayerIndex of the motion controller to -1 and then 0 when actually starting but that did not work. I’ve also tried the suggestion of making a child class of the motion controller and overriding the tick (like mentioned here MotionController Input for multi player - #13 by S_Q_R) but that still did work; the hands remained on the floor untracked.

I’m not too concerned at the moment of the other player seeing the hands move (which is replication related) but just to get the hands to track on the client.

I’m doing stuff mostly in C++, so in my GameMode class, this is how I spawn the player character:

void ATheDesertsRoseGameMode::PostLogin(APlayerController* newPlayer)
{
	FString levelName;
	FTransform playerSpawnTransform;
	FActorSpawnParameters spawnParams;
	ATheDesertsRosePlayerController* newCharacterPlayer;

	FUtils::WriteToLog(TEXT("PostLogin()"));

	Super::PostLogin(newPlayer);

	//Get the current level name and its corresponding spawn transform.
	levelName = GetWorld()->GetCurrentLevel()->OwningWorld->GetName();
	playerSpawnTransform = GetPlayerSpawnForLevel(levelName);

	newCharacterPlayer = Cast<ATheDesertsRosePlayerController>(newPlayer);
	newCharacterPlayer->PostLogin(levelName, playerSpawnTransform);
}

Then in my PlayerController class, I do the following to posess and initialize the player:

void ATheDesertsRosePlayerController::PostLogin(FString levelName, FTransform playerSpawnTransform)
{
	//Spawn the player and possess it with the newPlayer
	myPlayerCharacter = GetWorld()->SpawnActor<APlayerCharacter>(myPlayerCharacterBlueprint, playerSpawnTransform);
	
	//Have this controller possess the recently spawned player character.
	this->Possess(myPlayerCharacter);

	//Set the owner of the spawned character player to this controller.
	myPlayerCharacter->SetOwner(this);

	//Spawn and initialize the hands for the character.
	myPlayerCharacter->Initialize(this);
}

I call initialize on the player character and that spawns the two hands and attaches them to the player.

void APlayerCharacter::Initialize(APlayerController* newPlayer)
{
	FActorSpawnParameters spawnParams;

	FUtils::WriteToLog(TEXT("APlayerCharacter::Initialize()"));

	myBaseGameInstance = Cast<UBaseGameInstance>(this->GetGameInstance());

	myInventory = NewObject<UInventory>();
	myGameProgress = NewObject<UGameProgress>();

	//Set owner for left and right hands.
	spawnParams.Owner = this;

	//Create and spawn the two hands; specifics are specified in the blueprints.
	myLeftHand = GetWorld()->SpawnActor<APlayerHand>(myLeftHandBlueprint, spawnParams);
	myRightHand = GetWorld()->SpawnActor<APlayerHand>(myRightHandBlueprint, spawnParams);

	if (myLeftHand != NULL)
	{
		myLeftHand->AttachToComponent(RootComponent, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false), TEXT("LeftHandToCharacter"));
	}

	if (myRightHand != NULL)
	{
		myRightHand->AttachToComponent(RootComponent, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false), TEXT("RightHandToCharacter"));
	}

	myLeftHand->GetMotionController()->PlayerIndex = 0;
	myRightHand->GetMotionController()->PlayerIndex = 0;

	myLeftHand->EnableInput(newPlayer);
	myRightHand->EnableInput(newPlayer);
}

I’m wondering if it is an issue with EnableInput not being called on clients? I’m really not sure at this point why the hands on the client simply are not tracking.

HOLY BAGELS BATMAN! I ■■■■■■■ FIGURED IT OUT!

As usual, it was something very subtle. I needed to specify the owner of the spawned character BEFORE SPAWNING THE CHARACTER IN THE FActorSpawnParameters.

Here is the fix:

void ATheDesertsRosePlayerController::PostLogin(FString levelName, FTransform playerSpawnTransform)
{
	FActorSpawnParameters playerSpawnParams;

	//Set the owner of the spawned character player to this controller.
	playerSpawnParams.Owner = this;

	//Spawn the player and possess it with the newPlayer
	myPlayerCharacter = GetWorld()->SpawnActor<APlayerCharacter>(myPlayerCharacterBlueprint, playerSpawnTransform, playerSpawnParams);
	
	//Have this controller possess the recently spawned player character.
	this->Possess(myPlayerCharacter);

	//Spawn and initialize the hands for the character.
	myPlayerCharacter->Initialize(this);
}

Is there a version of this solution that would work in blueplrints? I am already setting the owner on the spawn actor node.

1 Like

When you set the owner in the blueprints:

  1. Are you sure your specifying the owner when spawning and not after?
  2. Make sure the owner is a player controller.

Let me know if that has any effect.

Hey @GregVFX! could you find a solution to this? i’m stuck on the same spot as you, same problem, working on blueprints, tried adding the player as owner on the spawn node, but it still does the same. Getting really frustrated with it, i’m so close to delivery date and i’m going crazy hahah
this is where im implementing the owner (selected in orange)
I would really apreciate any help

1 Like

Hi! Did you finally find a solution for this with blueprints? Thank you so much!

Hi! Have you solved? Thanks