when a custom struct is sent via RPC, is it serialized?

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.

struct FRepVehicleInput

	/* Input Axes. MUST be between -1.f and 1.f */
	float ThrustAxis;
	float StrafeAxis;
	float SteerAxis;
	float PitchAxis;
	float YawAxis;

	/*  Input states compressed to bytes (e.g, jump jets, afterburner) */
	uint8 ControlFlags;

	/* Constructor */
		: 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);

According to this, it does:

That’s a pretty awesome article you linked.

So why are you thinking it might not work? Because you’re using an RPC rather than variable replication? Pretty sure it shouldn’t matter. Remember to define the TStructOpsTypeTraits template though.

Yeah it was pretty helpful for me!

This particular struct goes both ways as replication and as part of an RPC, I just wondered (hoped) if the RPC would also serialize it (makes sense that it does). And yeah I got that one, learning many new things this week…