My network set up is through LAN and the Host has just a Default pawn so he is not actually a player. The Remotes controls PlayerPawn that drive from the same blueprint. The PlayerPawn bluerpint class is drived from C++ pawn class I made, Which just handles some basic replication stuff using C++. My problem is that the 1st player joins the Host all fine but When the 2nd player joins the Host his Game would just crash with the following Error Log. If I do the same replication logic in Blueprint everything works fine.
I attached the error log down blow, Also my C++ PlayerPawn class.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "PlayerPawn.generated.h"
class UMotionControllerComponent;
UCLASS()
class SWORDMKII_API APlayerPawn : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
APlayerPawn();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
//Hand and movement rep
UPROPERTY(ReplicatedUsing = OnRep_RightHandTrans)
FTransform DoRep_RightHandTrans;
UPROPERTY(ReplicatedUsing = OnRep_LeftHandTrans)
FTransform DoRep_LeftHandTrans;
UFUNCTION()
void OnRep_RightHandTrans();
UFUNCTION()
void OnRep_LeftHandTrans();
UFUNCTION(Server, Reliable, WithValidation)
void Server_UpdateRelativeTrans(FTransform Right, FTransform Left);
UFUNCTION(Client,Reliable)
void Client_ClientMovement(FTransform Trans);
UFUNCTION()
void UpdateHandTransLocal();
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
TArray<UMotionControllerComponent*> Controllers;
UMotionControllerComponent* RightHand;
UMotionControllerComponent* LeftHand;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "PlayerPawn.h"
#include "UnrealNetwork.h"
#include "MotionControllerComponent.h"
#include "HeadMountedDisplay.h"
// Sets default values
APlayerPawn::APlayerPawn()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void APlayerPawn::BeginPlay()
{
Super::BeginPlay();
//set up reference for motion controllers
this->GetComponents<UMotionControllerComponent>(Controllers);
RightHand = Controllers[0];
LeftHand = Controllers[1];
}
void APlayerPawn::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// Replicate to everyone
DOREPLIFETIME(APlayerPawn, DoRep_RightHandTrans);
DOREPLIFETIME(APlayerPawn, DoRep_LeftHandTrans);
}
void APlayerPawn::OnRep_RightHandTrans()
{
RightHand->SetRelativeTransform(DoRep_RightHandTrans);
}
void APlayerPawn::OnRep_LeftHandTrans()
{
LeftHand->SetRelativeTransform(DoRep_LeftHandTrans);
}
void APlayerPawn::Server_UpdateRelativeTrans_Implementation(FTransform Right, FTransform Left)
{
DoRep_RightHandTrans = Right;
DoRep_LeftHandTrans = Left;
//For server Repnotify
OnRep_RightHandTrans();
OnRep_LeftHandTrans();
}
bool APlayerPawn::Server_UpdateRelativeTrans_Validate(FTransform Right, FTransform Left)
{
return true;
}
void APlayerPawn::Client_ClientMovement_Implementation(FTransform Trans)
{
this->SetActorTransform(Trans);
}
void APlayerPawn::UpdateHandTransLocal()
{
if (this->IsLocallyControlled() == true)
{
DoRep_RightHandTrans = RightHand->GetRelativeTransform();
DoRep_LeftHandTrans = LeftHand->GetRelativeTransform();
}
}
// Called every frame
void APlayerPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//Rep for Hand and Body
UpdateHandTransLocal();
Server_UpdateRelativeTrans(DoRep_RightHandTrans, DoRep_LeftHandTrans);
if (this->HasAuthority())
{
Client_ClientMovement(this->GetActorTransform());
}
}
// Called to bind functionality to input
void APlayerPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}