Pitch Replication And Axis Compression In Unreal Engine
Source: Dev.to
The Pawn Class
The function GetBaseAimRotation() (available in the APawn class) returns the replicated pitch and can be used both in Blueprints and C++.
Blueprint Steps
- Call Get Base Aim Rotation and obtain its forward vector.
- Inverse‑transform that direction from world space to the pawn’s local space (using the pawn’s world transform).
- Break the resulting vector and read the Pitch component.

C++ Implementation
You can either use the Kismet Math Library or the native vector/rotator functions—both approaches give the same result.
Remember to include the appropriate header if you use the Kismet library (#include "Kismet/KismetMathLibrary.h").
Header
// MyCharacter.h
class AMyCharacter : public ACharacter
{
// ...
/** Returns the replicated pitch value. */
float GetReplicatedPitch() const;
};
Using Kismet Math Library
// MyCharacter.cpp
float AMyCharacter::GetReplicatedPitch() const
{
// World‑space aim direction from the replicated rotation
const FVector AimDirectionWorld = UKismetMathLibrary::GetForwardVector(GetBaseAimRotation());
// Convert to pawn‑local space
const FVector AimDirectionLocal = UKismetMathLibrary::InverseTransformDirection(
GetActorTransform(),
AimDirectionWorld
);
// Build a rotator from the local X axis and read Pitch
const FRotator AimRotationLocal = UKismetMathLibrary::MakeRotFromX(AimDirectionLocal);
return AimRotationLocal.Pitch;
}
Using Native Functions
float AMyCharacter::GetReplicatedPitch() const
{
// World‑space aim direction from the replicated rotation
const FVector AimDirectionWorld = GetBaseAimRotation().Vector();
// Convert to pawn‑local space (no scaling)
const FVector AimDirectionLocal = ActorToWorld().InverseTransformVectorNoScale(AimDirectionWorld);
// Build a rotator from the local vector and read Pitch
const FRotator AimRotationLocal = AimDirectionLocal.Rotation();
return AimRotationLocal.Pitch;
}
Both versions return the same pitch value that is replicated from the owning client.
Under the Hood
GetBaseAimRotation() works differently depending on whether the pawn has a valid controller (i.e., it is locally controlled) or not (i.e., it is a simulated proxy).
When a Controller Exists
FVector POVLoc;
FRotator POVRot;
if (Controller != nullptr && !InFreeCam())
{
Controller->GetPlayerViewPoint(POVLoc, POVRot);
return POVRot; // Use the player’s actual view rotation
}
The function simply returns the controller’s current view rotation.
When No Controller Exists (Simulated Proxy)
// Use the pawn’s own rotation as a fallback
POVRot = GetActorRotation();
// If the pitch is zero we fall back to the replicated RemoteViewPitch
if (FMath::IsNearlyZero(POVRot.Pitch))
{
const UWorld* World = GetWorld();
const UDemoNetDriver* DemoNetDriver = World ? World->GetDemoNetDriver() : nullptr;
// Replay/recording path – ignore for normal gameplay
if (DemoNetDriver && DemoNetDriver->IsPlaying() &&
DemoNetDriver->GetPlaybackEngineNetworkProtocolVersion() GetControlRotation().Pitch);
}
}
SetRemoteViewPitchconverts the floating‑point pitch into a byte (uint8) usingFRotator::CompressAxisToByte.- On the client side,
GetBaseAimRotation()expands that byte back into a fullfloatpitch withFRotator::DecompressAxisFromByte.
Summary
- Use
GetBaseAimRotation()to obtain the replicated view rotation. - Transform the forward vector to local space and extract the pitch (either via Kismet Math Library or native functions).
- Under the hood, Unreal compresses the pitch into a single byte (
RemoteViewPitch) on the server and decompresses it on remote clients, making the replication cheap and efficient.
You can apply the same pattern to replicate other axes or custom values by adding your own replicated, compressed variables and handling them in PreReplication.
Replicating Pawn Pitch in UE4
Below is the relevant code for handling pitch replication inside a pawn class.
1. Getting the Remote View Pitch
void APawn::GetRemoteViewPitch()
{
// Example of retrieving the remote view pitch
float Pitch = RemoteViewPitch; // RemoteViewPitch is a byte
float DecompressedPitch = FRotator::DecompressAxisFromByte(Pitch);
// Use DecompressedPitch as needed…
}
2. Setting the Remote View Pitch
void APawn::SetRemoteViewPitch(float NewRemoteViewPitch)
{
// Compress pitch to 1 byte
RemoteViewPitch = FRotator::CompressAxisToByte(NewRemoteViewPitch);
}
Note:
SetRemoteViewPitchcompresses afloataxis value into a single byte for network transmission.
How to Use This
- Inspect the pawn class – Open the pawn’s source file and locate the two functions above.
- Understand the flow –
SetRemoteViewPitchis called on the server (or owning client) to compress the pitch before it is replicated.GetRemoteViewPitch(or the corresponding getter you implement) decompresses the byte back into a usablefloaton remote machines.
- Leverage built‑in replication – In most cases you’ll rely on UE4’s default pitch replication for pawns.
- Custom axis compression – If you need to compress another axis, follow the same pattern: compress in a pre‑replication function and decompress when reading the replicated value.
Final Thoughts
Even if the details feel a bit overwhelming at first, revisiting these functions in the pawn class will help solidify your understanding. Most of the time the engine’s built‑in pitch replication is sufficient, but knowing how to manually compress an axis gives you flexibility for custom networking needs.
Good luck!