I have created a custom Movement system for myHovering Pawns, which uses both the engines default ‘Replicated Movement’ struct to ensure position information is the same on all clients, and it also replicates the Input from the keyboard given to the Pawn as well. I need the Input given to the pawn, to drive various visual and audible effects such as Engine sounds, thruster visualization and animation.
Pawns not controlled by the client receive their input data from the server via ‘ReplicatedInputStates’ - No different to how WheeledMovementComponent does it in the engine. If the Pawn is Locally Controlled, it performs a Server RPC (On Tick) which sends the Input from the keyboard to the server. The input is then replicated to everybody from the server. This is however, pretty expensive and the amount of RPC’s is far too high. Input is simulated locally first, and updated when it receives the ReplicatedInput from the Server.
The RPC sends a struct of the following data:
float ThrustValue
float StrafeValue
float SteerValue
float PitchValue
bool bIsJumping
Both ThrustValue and StrafeValue can only ever be in the range of -1.f to 1.f, and they only really need one decimal place of precision. Steer Value comes from the MouseX input and can therefore range quite significantly, whereas PitchValue can be any arbitrary value. Again though, both only require maybe 1-2 decimal places of precision.
I can quite easily setup a Timer that reduces the amount of RPC’s sent over the network. 10-Per Second would be more than enough. However, I feel as though there is more than enough potential to heavily optimized the replicated input states, since I don’t need the full floating-point precision.
How can I pack or Quantize these floats for more optimized RPC’s? Alternatively, is there a way I can handle this without using RPC’s at all, since RPC calls are expensive and the players WILL spend the majority of their time in possession of one of these craft.
Here’s some code, if it helps:
void ABZGame_HoverCraft::UpdateState(float DeltaTime) // Called On Tick. // TODO: Remove DeltaTime Pass-In
{
/* If we're the local object, we need to update the state of the input on the server. */
if (IsLocallyControlled())
{
/* Send Input States to Server. */
// TODO - This is currently an RPC every tick :O - need to find a more optimized way of doing this. (e.g., timer)
ServerUpdateState(InputStates);
}
else
{
/* Use Replicated Values For Remote Pawns */
InputStates = ReplicatedInputStates;
}
}
void ABZGame_HoverCraft::ServerUpdateState_Implementation(FHoverMovementStates InInputStates)
{
InputStates = InInputStates;
ReplicatedInputStates = InInputStates;
}
void ABZGame_HoverCraft::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ABZGame_HoverCraft, ReplicatedInputStates);
}