mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-11 17:30:00 +02:00
9.4 KiB
9.4 KiB
Multiplayer Testing Guide
Overview
Multiplayer testing validates network code, synchronization, and the player experience under real-world conditions. Network bugs are notoriously hard to reproduce—systematic testing is essential.
Test Categories
Synchronization Testing
| Test Type | Description | Priority |
|---|---|---|
| State sync | All clients see consistent game state | P0 |
| Position sync | Character positions match across clients | P0 |
| Event ordering | Actions occur in correct sequence | P0 |
| Conflict resolution | Simultaneous actions handled correctly | P1 |
| Late join | New players sync correctly mid-game | P1 |
Network Conditions
| Condition | Simulation Method | Test Focus |
|---|---|---|
| High latency | 200-500ms delay | Input responsiveness |
| Packet loss | 5-20% drop rate | State recovery |
| Jitter | Variable delay | Interpolation smoothness |
| Bandwidth limit | Throttle to 1Mbps | Data prioritization |
| Disconnection | Kill connection | Reconnection handling |
Test Scenarios
Basic Multiplayer
SCENARIO: Player Join/Leave
GIVEN host has started multiplayer session
WHEN Player 2 joins
THEN Player 2 appears in host's game
AND Player 1 appears in Player 2's game
AND player counts sync across all clients
SCENARIO: State Synchronization
GIVEN 4 players in match
WHEN Player 1 picks up item at position (10, 5)
THEN item disappears for all players
AND Player 1's inventory updates for all players
AND no duplicate pickups possible
SCENARIO: Combat Synchronization
GIVEN Player 1 attacks Player 2
WHEN attack hits
THEN damage is consistent on all clients
AND hit effects play for all players
AND health updates sync within 100ms
Network Degradation
SCENARIO: High Latency Gameplay
GIVEN 200ms latency between players
WHEN Player 1 moves forward
THEN movement is smooth on Player 1's screen
AND other players see interpolated movement
AND position converges within 500ms
SCENARIO: Packet Loss Recovery
GIVEN 10% packet loss
WHEN important game event occurs (goal, kill, etc.)
THEN event is eventually delivered
AND game state remains consistent
AND no duplicate events processed
SCENARIO: Player Disconnection
GIVEN Player 2 disconnects unexpectedly
WHEN 5 seconds pass
THEN other players are notified
AND Player 2's character handles gracefully (despawn/AI takeover)
AND game continues without crash
Edge Cases
SCENARIO: Simultaneous Actions
GIVEN Player 1 and Player 2 grab same item simultaneously
WHEN both inputs arrive at server
THEN only one player receives item
AND other player sees consistent state
AND no item duplication
SCENARIO: Host Migration
GIVEN host disconnects
WHEN migration begins
THEN new host is selected
AND game state transfers correctly
AND gameplay resumes within 10 seconds
SCENARIO: Reconnection
GIVEN Player 2 disconnects temporarily
WHEN Player 2 reconnects within 60 seconds
THEN Player 2 rejoins same session
AND state is synchronized
AND progress is preserved
Network Simulation Tools
Unity
// Using Unity Transport with Network Simulator
using Unity.Netcode;
public class NetworkSimulator : MonoBehaviour
{
[SerializeField] private int latencyMs = 100;
[SerializeField] private float packetLossPercent = 5f;
[SerializeField] private int jitterMs = 20;
void Start()
{
var transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
var simulator = transport.GetSimulatorParameters();
simulator.PacketDelayMS = latencyMs;
simulator.PacketDropRate = (int)(packetLossPercent * 100);
simulator.PacketJitterMS = jitterMs;
}
}
// Test
[UnityTest]
public IEnumerator Position_UnderLatency_ConvergesWithinThreshold()
{
EnableNetworkSimulation(latencyMs: 200);
// Move player
player1.Move(Vector3.forward * 10);
yield return new WaitForSeconds(1f);
// Check other client's view
var player1OnClient2 = client2.GetPlayerPosition(player1.Id);
var actualPosition = player1.transform.position;
Assert.Less(Vector3.Distance(player1OnClient2, actualPosition), 0.5f);
}
Unreal
// Using Network Emulation
void UNetworkTestHelper::EnableLatencySimulation(int32 LatencyMs)
{
if (UNetDriver* NetDriver = GetWorld()->GetNetDriver())
{
FPacketSimulationSettings Settings;
Settings.PktLag = LatencyMs;
Settings.PktLagVariance = LatencyMs / 10;
Settings.PktLoss = 0;
NetDriver->SetPacketSimulationSettings(Settings);
}
}
// Functional test for sync
void AMultiplayerSyncTest::StartTest()
{
Super::StartTest();
// Spawn item on server
APickupItem* Item = GetWorld()->SpawnActor<APickupItem>(
ItemClass, FVector(0, 0, 100));
// Wait for replication
FTimerHandle TimerHandle;
GetWorld()->GetTimerManager().SetTimer(TimerHandle, [this, Item]()
{
// Verify client has item
if (VerifyItemExistsOnAllClients(Item))
{
FinishTest(EFunctionalTestResult::Succeeded, "Item replicated");
}
else
{
FinishTest(EFunctionalTestResult::Failed, "Item not found on clients");
}
}, 2.0f, false);
}
Godot
# Network simulation
extends Node
var simulated_latency_ms := 0
var packet_loss_percent := 0.0
func _ready():
# Hook into network to simulate conditions
multiplayer.peer_packet_received.connect(_on_packet_received)
func _on_packet_received(id: int, packet: PackedByteArray):
if packet_loss_percent > 0 and randf() < packet_loss_percent / 100:
return # Drop packet
if simulated_latency_ms > 0:
await get_tree().create_timer(simulated_latency_ms / 1000.0).timeout
_process_packet(id, packet)
# Test
func test_position_sync_under_latency():
NetworkSimulator.simulated_latency_ms = 200
# Move player on host
host_player.position = Vector3(100, 0, 100)
await get_tree().create_timer(1.0).timeout
# Check client view
var client_view_position = client.get_remote_player_position(host_player.id)
var distance = host_player.position.distance_to(client_view_position)
assert_lt(distance, 1.0, "Position should converge within 1 unit")
Dedicated Server Testing
Test Matrix
| Scenario | Test Focus |
|---|---|
| Server startup | Clean initialization, port binding |
| Client authentication | Login validation, session management |
| Server tick rate | Consistent updates under load |
| Maximum players | Performance at player cap |
| Server crash recovery | State preservation, reconnection |
Load Testing
SCENARIO: Maximum Players
GIVEN server configured for 64 players
WHEN 64 players connect
THEN all connections succeed
AND server tick rate stays above 60Hz
AND latency stays below 50ms
SCENARIO: Stress Test
GIVEN 64 players performing actions simultaneously
WHEN running for 10 minutes
THEN no memory leaks
AND no desync events
AND server CPU below 80%
Matchmaking Testing
SCENARIO: Skill-Based Matching
GIVEN players with skill ratings [1000, 1050, 2000, 2100]
WHEN matchmaking runs
THEN [1000, 1050] are grouped together
AND [2000, 2100] are grouped together
SCENARIO: Region Matching
GIVEN players from US-East, US-West, EU
WHEN matchmaking runs
THEN players prefer same-region matches
AND cross-region only when necessary
AND latency is acceptable for all players
SCENARIO: Queue Timeout
GIVEN player waiting in queue
WHEN 3 minutes pass without match
THEN matchmaking expands search criteria
AND player is notified of expanded search
Security Testing
| Vulnerability | Test Method |
|---|---|
| Speed hacking | Validate movement on server |
| Teleportation | Check position delta limits |
| Damage hacking | Server-authoritative damage |
| Packet injection | Validate packet checksums |
| Replay attacks | Use unique session tokens |
Performance Metrics
| Metric | Good | Acceptable | Poor |
|---|---|---|---|
| Round-trip latency | < 50ms | < 100ms | > 150ms |
| Sync delta | < 100ms | < 200ms | > 500ms |
| Packet loss tolerance | < 5% | < 10% | > 15% |
| Bandwidth per player | < 10 KB/s | < 50 KB/s | > 100 KB/s |
| Server tick rate | 60+ Hz | 30+ Hz | < 20 Hz |
Best Practices
DO
- Test with real network conditions, not just localhost
- Simulate worst-case scenarios (high latency + packet loss)
- Use server-authoritative design for competitive games
- Implement lag compensation for fast-paced games
- Test host migration paths
- Log network events for debugging
DON'T
- Trust client data for important game state
- Assume stable connections
- Skip testing with maximum player counts
- Ignore edge cases (simultaneous actions)
- Test only in ideal network conditions
- Forget to test reconnection flows