Hi,
I was trying to follow this tutorial (Accurately syncing Unreal’s network clock | by Josh Sutphin | Medium), and they seem to be modifying the playercontroller directly in the following snippets, even though they say they are changing a custom player controller: (the names of the files are not shown in the website)
PlayerController.h
public:
/** Returns the network-synced time from the server.
* Corresponds to GetWorld()->GetTimeSeconds()
* on the server. This doesn't actually make a network
* request; it just returns the cached, locally-simulated
* and lag-corrected ServerTime value which was synced
* with the server at the time of this PlayerController's
* last restart. */
virtual float GetServerTime() { return ServerTime; }
virtual void ReceivedPlayer() override;
protected:
/** Reports the current server time to clients in response
* to ServerRequestServerTime */
UFUNCTION(Client, Reliable)
void ClientReportServerTime(
float requestWorldTime,
float serverTime
);
/** Requests current server time so accurate lag
* compensation can be performed in ClientReportServerTime
* based on the round-trip duration */
UFUNCTION(Server, Reliable, WithValidation)
void ServerRequestServerTime(
APlayerController* requester,
float requestWorldTime
);
float ServerTime = 0.0f;
PlayerController.cpp
void APlayerController::ServerRequestServerTime_Implementation(
APlayerController* requester,
float requestWorldTime
)
{
float serverTime = GetWorld()->GetGameState()->
GetServerWorldTimeSeconds();
ClientReportServerTime(requestWorldTime, serverTime);
}
bool APlayerController::ServerRequestServerTime_Validate(
APlayerController* requester,
float requestWorldTime
)
{
return true;
}
void APlayerController::ClientReportServerTime_Implementation(
float requestWorldTime,
float serverTime
)
{
// Apply the round-trip request time to the server's
// reported time to get the up-to-date server time
float roundTripTime = GetWorld()->GetTimeSeconds() -
requestWorldTime;
float adjustedTime = serverTime + (roundTripTime * 0.5f);
ServerTime = adjustedTime;
}
void APlayerController::ReceivedPlayer()
{
Super::ReceivedPlayer();
if(IsLocalController())
{
ServerRequestServerTime(
this,
GetWorld()->GetTimeSeconds()
);
}
}
And their game state cpp file:
float ACustomGameState::GetServerWorldTimeSeconds() const
{
if(APlayerController* pc = GetGameInstance()->
GetFirstLocalPlayerController(GetWorld())
)
{
return pc->GetServerTime();
}
else
{
return GetWorld()->GetTimeSeconds();
}
}
I initially tried to override the base APlayerController directly in a file as they seemed to be doing, but I couldn’t work out how to go about it, and am not sure it would work as even if I define the functions under APlayerController:: then the properties required (ServerTime) are still under my custom player controller.
Then I tried making my own custom player controller class, derived from APlayerController:
FPSPlayerController.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "GameFramework/GameStateBase.h"
#include "FPSPlayerController.generated.h"
/**
*
*/
UCLASS()
class FPSGAME_API AFPSPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AFPSPlayerController();
//https://medium.com/@invicticide/accurately-syncing-unreals-network-clock-87a3f9262594
/** Returns the network-synced time from the server.
* Corresponds to GetWorld()->GetTimeSeconds()
* on the server. This doesn't actually make a network
* request; it just returns the cached, locally-simulated
* and lag-corrected ServerTime value which was synced
* with the server at the time of this PlayerController's
* last restart. */
virtual float GetServerTime() { return ServerTime; }
virtual void ReceivedPlayer() override;
protected:
/** Reports the current server time to clients in response
* to ServerRequestServerTime */
UFUNCTION(Client, Reliable)
void ClientReportServerTime(
float requestWorldTime,
float serverTime
);
/** Requests current server time so accurate lag
* compensation can be performed in ClientReportServerTime
* based on the round-trip duration */
UFUNCTION(Server, Reliable, WithValidation)
void ServerRequestServerTime(
APlayerController* requester,
float requestWorldTime
);
float ServerTime = 0.0f;
};
FPSPlayerController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "fpsgame.h"
#include "FPSPlayerController.h"
AFPSPlayerController::AFPSPlayerController()
{
APlayerController();
}
void AFPSPlayerController::ServerRequestServerTime_Implementation(
APlayerController* requester,
float requestWorldTime
)
{
float serverTime = GetWorld()->GetGameState()->
GetServerWorldTimeSeconds();
ClientReportServerTime(requestWorldTime, serverTime);
}
bool AFPSPlayerController::ServerRequestServerTime_Validate(
APlayerController* requester,
float requestWorldTime
)
{
return true;
}
void AFPSPlayerController::ClientReportServerTime_Implementation(
float requestWorldTime,
float serverTime
)
{
// Apply the round-trip request time to the server's
// reported time to get the up-to-date server time
float roundTripTime = GetWorld()->GetTimeSeconds() -
requestWorldTime;
float adjustedTime = serverTime + (roundTripTime * 0.5f);
ServerTime = adjustedTime;
}
void AFPSPlayerController::ReceivedPlayer()
{
Super::ReceivedPlayer();
if (IsLocalController())
{
ServerRequestServerTime(
this,
GetWorld()->GetTimeSeconds()
);
}
}
And implemented the custom game state as shown on the website, with the h file:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameState.h"
#include "FPSGameState.generated.h"
/**
*
*/
UCLASS()
class FPSGAME_API AFPSGameState : public AGameState
{
GENERATED_BODY()
public:
float GetServerWorldTimeSeconds() const;
};
This doesn’t work either, as AFPSPlayerController* pc = GetGameInstance()-> GetFirstLocalPlayerController(GetWorld())
comes up with an error: "A value of type "APlayerController * " Cannot be used to initialize an entity of type “AFPSPlayerController*”
I’m extremely confused as to how to get this to work, and need it to be able to progress with my project. Please could someone help me?
I will be happy to reply with any more needed information.