BMAD-METHOD/src/modules/bmgd/gametest/knowledge/multiplayer-testing.md

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