Yeah you are right I forgot to do that.
The only thing left now is that the server doesn’t rotate at all and I understand why because I am doing things if the client does not have Authority but I can’t seem to figure out how to do it on the server.
I tried multiple things but every time I end up with the server rotating all the characters again.
If the mouse is active in the server client the following things happen:
Server client -> All clients including the server client rotate towards the mouse position.
Every other client -> See’s all the characters rotate except their own.
If the mouse is active in any other client that is not the server:
Server client -> The active client character gets rotated correctly
Active client -> Character rotates correctly towards the mouse position.
Other clients -> The active client character gets rotated correctly
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "SaltCharacter.generated.h"
UCLASS()
class SALT_API ASaltCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ASaltCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Camera)
class UCameraComponent* CameraComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Camera)
class USpringArmComponent* CameraBoom;
// Saved player direction
FVector DirectionFaced;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void MoveForward(float Val);
void MoveRight(float Val);
private:
UPROPERTY(Replicated, ReplicatedUsing=OnRep_SetServerRotation)
FRotator R_ServerRotation;
UFUNCTION()
void OnRep_SetServerRotation();
UFUNCTION(Server, Reliable, WithValidation)
void Server_CalculateRotation(FVector WorldLocation, FVector WorldDirection, FVector ActorLocation);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "SaltCharacter.h"
#include "Player/SaltPlayerController.h"
#include "Engine/Engine.h"
#include "Net/UnrealNetwork.h"
#include "Kismet/KismetMathLibrary.h"
#include "Runtime/Engine/Classes/GameFramework/SpringArmComponent.h"
#include "Runtime/Engine/Classes/Camera/CameraComponent.h"
// Sets default values
ASaltCharacter::ASaltCharacter()
{
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(GetRootComponent());
CameraBoom->bAbsoluteRotation = true;
CameraBoom->TargetArmLength = 1200.f;
CameraBoom->RelativeRotation = FRotator(-60.f, 0.f, 0.f);
CameraBoom->bDoCollisionTest = false;
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
CameraComponent->bUsePawnControlRotation = false;
GetMesh()->bOnlyOwnerSee = false;
GetMesh()->bOwnerNoSee = false;
GetMesh()->bReceivesDecals = false;
GetMesh()->SetCollisionObjectType(ECC_Pawn);
GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
// Set this character 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 ASaltCharacter::BeginPlay()
{
Super::BeginPlay();
ASaltPlayerController* MyPC = Cast<ASaltPlayerController>(GetController());
if (MyPC)
{
MyPC->bShowMouseCursor = true;
MyPC->bEnableClickEvents = true;
MyPC->bEnableMouseOverEvents = true;
}
}
// Called every frame
void ASaltCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
ASaltPlayerController* MyPC = Cast<ASaltPlayerController>(GetController());
if (MyPC)
{
FVector WorldLocation;
FVector WorldDirection;
FPlane Plane = FPlane(0.f, 0.f, 1.f, 0.f);
float t;
FVector IntersectionPoint;
FVector ActorLocation = GetActorLocation();
MyPC->DeprojectMousePositionToWorld(WorldLocation, WorldDirection);
WorldDirection = WorldDirection * 100000;
if (Role < ROLE_Authority)
{
if (UKismetMathLibrary::LinePlaneIntersection(WorldLocation, WorldLocation + WorldDirection, Plane, t, IntersectionPoint))
{
FVector dir = (IntersectionPoint - ActorLocation).GetSafeNormal();
DirectionFaced = FVector(dir.X, dir.Y, 0.f);
FRotator LookAtRot = UKismetMathLibrary::FindLookAtRotation(ActorLocation, IntersectionPoint);
FRotator NewRot = FRotator(0.f, LookAtRot.Yaw, 0.f);
SetActorRotation(NewRot);
}
Server_CalculateRotation(WorldLocation, WorldDirection, ActorLocation);
}
}
}
// Called to bind functionality to input
void ASaltCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &ASaltCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ASaltCharacter::MoveRight);
}
void ASaltCharacter::MoveForward(float Val)
{
FVector Direction = FRotationMatrix(GetController()->GetControlRotation()).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Val);
}
void ASaltCharacter::MoveRight(float Val)
{
FVector Direction = FRotationMatrix(GetController()->GetControlRotation()).GetScaledAxis(EAxis::Y);
AddMovementInput(Direction, Val);
}
void ASaltCharacter::OnRep_SetServerRotation()
{
SetActorRotation(R_ServerRotation);
}
void ASaltCharacter::Server_CalculateRotation_Implementation(FVector WorldLocation, FVector WorldDirection, FVector ActorLocation)
{
FPlane Plane = FPlane(0.f, 0.f, 1.f, 0.f);
float t;
FVector IntersectionPoint;
if (UKismetMathLibrary::LinePlaneIntersection(WorldLocation, WorldLocation + WorldDirection, Plane, t, IntersectionPoint))
{
FVector dir = (IntersectionPoint - ActorLocation).GetSafeNormal();
DirectionFaced = FVector(dir.X, dir.Y, 0.f);
FRotator LookAtRot = UKismetMathLibrary::FindLookAtRotation(ActorLocation, IntersectionPoint);
FRotator NewRot = FRotator(0.f, LookAtRot.Yaw, 0.f);
R_ServerRotation = NewRot;
OnRep_SetServerRotation();
}
}
bool ASaltCharacter::Server_CalculateRotation_Validate(FVector WorldLocation, FVector WorldDirection, FVector ActorLocation)
{
return true;
}
void ASaltCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty> & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ASaltCharacter, R_ServerRotation);
}