In this lesson, you will learn how to implement rigorous server-side verification to ensure that incoming client RPCs conform to game rules rather than allowing arbitrary data manipulation.
The Foundation of Trust
In Unreal Engine’s client-server architecture, the client is inherently untrusted. Even if you implement client-side prediction for snappy movement, the server remains the final arbiter of truth. "Validation" refers to the practice of checking the logical feasibility of a client’s request before processing it. Without this, a malicious or lagging client could spoof values, such as sending a "FireWeapon" RPC with an impossible weapon ID or an out-of-bounds damage value.
Implementing Validation Logic
The most robust way to handle this is through WithValidation RPCs. When you define an RPC as ServerWithValidation, Unreal generates an _Validate function that the server executes before the primary implementation function. If the validation function returns false, the server ignores the RPC and can even disconnect the client for "cheat-like" behavior.
Consider a system where a player claims they have picked up a specific power-up:
// Header
UFUNCTION(Server, Reliable, WithValidation)
void Server_ClaimPowerup(int32 PowerupID);
// Implementation
bool AMyPlayerController::Server_ClaimPowerup_Validate(int32 PowerupID)
{
// Check if the PowerupID is within the expected range
// AND check if the player is actually close enough to the powerup actor
if (PowerupID < 0 || PowerupID >= MaxPowerups) return false;
APowerup* Target = GetPowerupByID(PowerupID);
return Target && Target->GetDistanceTo(this->GetPawn()) < InteractionRange;
}
void AMyPlayerController::Server_ClaimPowerup_Implementation(int32 PowerupID)
{
// Only executed if Validate returned true
PerformClaimLogic(PowerupID);
}
Preventing State Desynchronization
Validation logic isn't just about security; it’s about state integrity. If a client attempts to perform an action that conflicts with the server's current state—such as firing a weapon while stunned—the validation layer catches the desync early. By checking parameters against the server's authoritative state (like player location, inventory, or cooldown timers), you ensure that every RPC confirms the client’s intent aligns with the server’s reality.
Key Takeaway: Never trust client-provided data; always use WithValidation to reject unauthorized actions before they reach your gameplay logic.