In this lesson, you will learn how to measure and stress-test the CPU and network overhead of your character movement implementation to ensure your game remains performant under high load.
As you scale toward higher player counts, the CharacterMovementComponent (CMC) is often the most expensive system in your game due to the constant loop of prediction, reconciliation, and bandwidth consumption. Profiling isn't just about finding bugs; it’s about understanding the "cost per actor" so you can plan for your target player concurrency.
CPU Profiling: The Cost of Reconciliation
When profiling CPU usage, focus on the PerformMovement and ClientReplicateMoveToServer functions. In Unreal Insights, look for spikes in the GameThread or TaskGraph during high-speed movement. If your custom movement logic involves complex PhysCustom calculations, you are likely performing a heavy loop on every tick. If your CPU cost spikes during reconciliation, it’s a sign that your logic is too heavy to run multiple times per frame when the server corrects a client’s state.
Use the stat game and stat net commands in the console to monitor these costs in real-time. If the NetUpdateFrequency is set too high for your character class, you are wasting CPU cycles packing data that doesn't significantly improve the visual experience.
Network Profiling: Bandwidth Overhead
Network performance is defined by your packet size and frequency. Even with CharacterMovementComponent optimizations, adding custom replicated variables adds up across 32 or 64 players. Use netprofile to capture data over a few minutes of gameplay, then open the file in the Network Profiler tool.
Look for the "Bunch size" and "RPC count." If you are sending unreliable RPCs for minor state updates too frequently, you will saturate the buffer.
// Check if your character is being updated too often
void AMyCharacter::GetLifetimeReplicatedProps(TArray<FLifelineProperty>& OutLifetimeProps) const {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// Be mindful: adding too many properties here increases per-packet overhead
DOREPLIFETIME(AMyCharacter, MyCustomState);
}
To stress-test, use the Network Emulation settings in the Editor (PIE) to simulate "Bad" network conditions (high packet loss and jitter). Observe how your movement component handles "rollback" and "re-simulation"—if the CPU cost jumps massively during high-loss scenarios, your reconciliation logic is likely too expensive.
Key Takeaway: Profile both the steady-state CPU cost of your movement logic and the peak cost during reconciliation to ensure your system survives both high player counts and unstable network conditions.