So I’ve created a custom struct, which has an override for the NetSerialize() function. What I want to know is, if I send this struct to the server via an RPC from a client, does it still serialize?
Here’s the vast proportion of my struct. You can see that I compress the floats to bytes for serialization, and that’s how I want the data to be sent.
USTRUCT()
struct FRepVehicleInput
{
GENERATED_USTRUCT_BODY()
/* Input Axes. MUST be between -1.f and 1.f */
UPROPERTY(Transient)
float ThrustAxis;
UPROPERTY(Transient)
float StrafeAxis;
UPROPERTY(Transient)
float SteerAxis;
UPROPERTY(Transient)
float PitchAxis;
UPROPERTY(Transient)
float YawAxis;
/* Input states compressed to bytes (e.g, jump jets, afterburner) */
UPROPERTY(Transient)
uint8 ControlFlags;
/* Constructor */
FRepVehicleInput()
: ThrustAxis(0.f)
, StrafeAxis(0.f)
, SteerAxis(0.f)
, PitchAxis(0.f)
, YawAxis(0.f)
, ControlFlags(0)
{}
/* Binary Serialization */
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
// Start as True
bOutSuccess = true;
// Write Packing
uint8 ByteThrust = CompressByte(ThrustAxis);
uint8 ByteStrafe = CompressByte(StrafeAxis);
uint8 ByteSteer = CompressByte(SteerAxis);
uint8 BytePitch = CompressByte(PitchAxis);
uint8 ByteYaw = CompressByte(YawAxis);
uint8 ByteControl = ControlFlags;
uint8 B = (ByteThrust != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << ByteThrust; else ByteThrust = 0;
B = (ByteStrafe != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << ByteStrafe; else ByteStrafe = 0;
B = (ByteSteer != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << ByteSteer; else ByteSteer = 0;
B = (BytePitch != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << BytePitch; else BytePitch = 0;
B = (ByteYaw != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << ByteYaw; else ByteYaw = 0;
B = (ByteControl != 0);
Ar.SerializeBits(&B, 1);
if (B) Ar << ByteControl; else ByteControl = 0;
if (Ar.IsLoading())
{
ThrustAxis = DecompressByte(ByteThrust);
StrafeAxis = DecompressByte(ByteStrafe);
SteerAxis = DecompressByte(ByteSteer);
PitchAxis = DecompressByte(BytePitch);
YawAxis = DecompressByte(ByteYaw);
ControlFlags = ByteControl;
}
return true;
}
/* Compress / Decompress Axes to Bytes */
FORCEINLINE uint8 CompressByte(const float X) const
{
// Need an ODD number of combinations so that we can quantize perfectly to zero.
return (uint8)(((X * 0.5f) + 0.5f) * 254);
}
FORCEINLINE float DecompressByte(const uint8 X) const
{
return (((float)X / 254.f) * 2.f) - 1.f;
}
And I’m just sending it like so:
/* Called by Client to tell server to simulate this move. If the server is happy with the move */
UFUNCTION(Unreliable, Server, WithValidation)
virtual void ServerSimulateInput(float TimeStamp, FRepVehicleInput PackedStates);
virtual void ServerSimulateInput_Implementation(float TimeStamp, FRepVehicleInput PackedStates);
virtual bool ServerSimulateInput_Validate(float TimeStamp, FRepVehicleInput PackedStates);