Hi . We went ahead with our investigations on how to use Oculus Avatars and we finally succeeded in replicating an Avatar and its movements.
We followed a different approach compared with the one suggested by you some posts ago.
Basically, we didn’t use the RemoteAvatar, only LocalAvatar (since both use OvrAvatar, wich actually is the avatar). So we spawn a LocalAvatar for each player and, with the GameMode, we call [FONT=courier new]Possess on the right PlayerController.
Secondly, in the LocalAvatar’s [FONT=courier new]Restart method, we set OvrAvatar’s [FONT=courier new]PlayerType as Local or Remote, just by checking if the avatar is controlled by me or not:
void ALocalAvatar::Restart() {
if (IsControlledPawn()) {
AvatarComponent->SetVisibilityType(ovrAvatarVisibilityFlag_FirstPerson);
AvatarComponent->SetPlayerType(UOvrAvatar::ePlayerType::Local);
}
else {
AvatarComponent->SetVisibilityType(ovrAvatarVisibilityFlag_ThirdPerson);
AvatarComponent->SetPlayerType(UOvrAvatar::ePlayerType::Remote);
}
}
bool ALocalAvatar::IsControlledPawn() {
return Controller == GetWorld()->GetFirstPlayerController();
}
Finally, the replication part, we defined a custom struct, called OculusTransform, which simply lets us convert an [FONT=courier new]ovrAvatarTransform in a “replicable” format (since a property has to be a USTRUCT, UCLASS or UENUM in order to be replicable).
In OvrAvatar we defined these three properties:
UPROPERTY(Replicated)
FOculusTransform RightHandReplicatedTransform;
UPROPERTY(Replicated)
FOculusTransform LeftHandReplicatedTransform;
UPROPERTY(Replicated)
FOculusTransform BodyReplicatedTransform;
So we applied this logic in the OvrAvatar’s [FONT=courier new]TickComponent method:
- If the pawn is controlled by me, I put the data from [FONT=courier new]HandInputState[ovrHand_Left].transform, [FONT=courier new]HandInputState[ovrHand_Right].transform and [FONT=courier new]BodyTransform in these three structures (passing them to the server with an appropriate server-replicated function, so that they can be replicated).
- Otherwise, I pick the data from these three structures and put them in [FONT=courier new]HandInputState[ovrHand_Left].transform, [FONT=courier new]HandInputState[ovrHand_Right].transform and [FONT=courier new]BodyTransform. In this latter case we also need to call [FONT=courier new]ovrAvatarPose_UpdateHands and [FONT=courier new]ovrAvatarPose_UpdateBody, because [FONT=courier new]UpdateTransforms does nothing on remote avatars (as you can see from code).
This is all. Hands and body are now correctly replicated. We are now working on replicating fingers’ position.
Further details:
Obviously we also set [FONT=courier new]bReplicates = true in LocalAvatar and OvrAvatar constructors, and also [FONT=courier new]bAlwaysRelevant = true in LocalAvatar. Also added all the other stuffs in order to have variables correctly replicated.
In LocalAvatar’s [FONT=courier new]SetupPlayerInputComponent we do nothing if the pawn is not controlled by me.
Write me if you need/want to know something else.