@PenguinTD @devel.bmad @mordentral
Thanks all for the tips. I adjusted some parameters but nada. The problem is still the MotionController Component does not receive input from the client side.
Here’s is more detail the flow:
1)Pawn #1 (listen-server via Steam) spawns BP_MotionController. Pawn #2 (client) will follow later.
&stc=1
So at this point the pawn owns BP_MotionController_0 and _1, which in return own their MotionController Component
Server set a reference variable with RepNotify for BP_MotionController exist for everybody. There, client should have a replicate of BP_MotionController and control the MotionControllerComponent inside.
Within RepNotify, Player Index of the MotionController Component is set to 0, ultimately owned by the locally controlled pawn. The, the server attach the BP_MotionController to the root (VRORigin).
&stc=1
Then at every tick, on the server and the client, the worldtransform of the controllers are captured then RepNotified from the Server to everybody.
&stc=1
On RepNotify, transforms are replicated to everybody and local pawns get local variables
&stc=1
Finally some fine-tuning stuff
&stc=1
The result the same: Pawns see each other, their face and controllers. But motioncontrollers are not associated with client (Pawn #2) hands. They are still at VROrigin location, but animation works.
I tried with/without C++ changes, the same.
Original code:
bool UMotionControllerComponent::PollControllerState(FVector& Position, FRotator& Orientation)
{
if (IsInGameThread())
{
// Cache state from the game thread for use on the render thread
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);
}
if ((PlayerIndex != INDEX_NONE) && bHasAuthority)
{
TArray<IMotionController*> MotionControllers = IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>( IMotionController::GetModularFeatureName() );
for( auto MotionController : MotionControllers )
{
if ((MotionController != nullptr) && MotionController->GetControllerOrientationAndPosition(PlayerIndex, Hand, Orientation, Position))
{
CurrentTrackingStatus = MotionController->GetControllerTrackingStatus(PlayerIndex, Hand);
return true;
}
}
}
return false;
}
Modified code:
bool UMotionControllerComponent::PollControllerState(FVector& Position, FRotator& Orientation)
{
if (IsInGameThread())
{
// Cache state from the game thread for use on the render thread
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);
}
if ((PlayerIndex != INDEX_NONE) && bHasAuthority)
{
TArray<IMotionController*> MotionControllers = IModularFeatures::Get().GetModularFeatureImplementations<IMotionController>( IMotionController::GetModularFeatureName() );
for( auto MotionController : MotionControllers )
{
if ((MotionController != nullptr) && MotionController->GetControllerOrientationAndPosition(PlayerIndex, Hand, Orientation, Position))
{
CurrentTrackingStatus = MotionController->GetControllerTrackingStatus(PlayerIndex, Hand);
return true;
}
}
}
return false;
}
I’m stuck as an old gum under a park bench on a summer day.