Client-side prediction with server reconciliation for Godot 4.x
The Rollback Netcode Plugin provides a complete, production-ready networking solution for multiplayer Godot games that require instant input response and server-authoritative gameplay. Built on proven rollback netcode principles used in competitive fighting games and real-time action titles, this plugin eliminates the input lag typically associated with networked multiplayer while maintaining server authority to prevent cheating.
Traditional client-server networking forces players to wait for round-trip confirmation before seeing their actions, creating noticeable delay (50-150ms on typical connections). This plugin solves this problem by predicting player actions locally and automatically reconciling differences when the server's authoritative state arrives, providing instant visual feedback without sacrificing server control.
The plugin is extracted from Hop 'n Bop, a production multiplayer action game, and comes with comprehensive testing (80+ unit tests), clear architectural patterns, and working examples to get you started quickly.
- Frame-synchronous simulation at 60 FPS - Deterministic game logic decoupled from render framerate
- Client-side prediction - Instant local input response with zero perceived lag
- Server-authoritative validation - Server controls game state to prevent cheating
- Automatic rollback reconciliation - Smooth correction when predictions differ from server
- NTP-like frame synchronization - Client-server frame index sync to prevent drift
- Configurable rollback buffer - Adjustable history duration (default: 1.5 seconds / ~90 frames)
- ENet peer management - Built-in connection handling with MultiplayerAPI integration
- Optional performance tracking - Real-time metrics and profiling tools
- Resource-based configuration - Inspector-friendly NetworkSettings .tres files
- Extensible state management - ReconcilableState base class for custom entities
- Memory-efficient - ArrayPool reduces GC pressure from frequent state snapshots
- Production-tested - 80+ unit tests covering core networking infrastructure
- Complete working examples - Simple game demonstrating all features
- Open Godot Editor
- Navigate to AssetLib tab
- Search for "Rollback Netcode"
- Click Download and Install
- Enable plugin in Project > Project Settings > Plugins
- Clone or download this repository
- Copy
addons/rollback_netcode/to your project'saddons/folder - Restart Godot Editor
- Enable plugin in Project > Project Settings > Plugins
- Verify plugin loaded by checking for NetworkOrchestrator autoload
extends Node
# 1. Create NetworkOrchestrator with config
var config := preload("res://network_settings.tres")
var netcode := NetworkOrchestrator.new(config, MyLogger.new(), MyTime.new())
func _ready() -> void:
# 2. Add to scene tree
add_child(netcode)
# 3. Start server or connect client
if "--server" in OS.get_cmdline_args():
netcode.connector.start_server()
else:
netcode.connector.connect_to_server("127.0.0.1")For a complete integration guide, see QUICKSTART.md.
For a working example, see examples/simple_game/.
Unlike traditional delta-time game loops, frame-synchronous simulation runs game logic at a fixed tick rate (60 FPS) independent of rendering. This ensures deterministic behavior across all clients, making rollback reconciliation possible. Rendering still runs at full framerate for smooth visuals.
When a player presses a button, the client immediately simulates the predicted result (movement, attack, etc.) without waiting for server confirmation. This provides instant visual feedback while the input is sent to the server in parallel.
When the server's authoritative state arrives and differs from the client's prediction, reconciliation corrects the client:
- Roll back to the mismatched frame
- Apply the server's correct state
- Re-simulate all frames from mismatch to present
- Visual state smoothly catches up
A circular buffer maintains historical game states (default: 1.5 seconds). When a mismatch is detected, the system "rewinds time" to the incorrect frame, applies corrections, and fast-forwards back to the present with corrected data.
The base class for all networked entities. Subclass ReconcilableState and implement state packing/unpacking to automatically gain client prediction, server authority, and rollback support.
NetworkOrchestrator (Singleton)
├── NetworkConnector (ENet peer management)
├── FrameDriver (Frame-sync simulation loop)
├── FrameSynchronizer (NTP-like frame sync)
└── PerfTracker (optional) (Performance monitoring)
ReconcilableState (Base Class)
├── Integrates with Godot MultiplayerSynchronizer
├── Manages RollbackBuffer for entity
└── Coordinates with FrameDriver for simulation
Key Components:
- NetworkOrchestrator: Central coordinator providing access to all subsystems
- NetworkConnector: Handles ENet connections, disconnections, and peer management
- FrameDriver: Runs frame-synchronous simulation at 60 FPS, orchestrates rollback
- FrameSynchronizer: Maintains synchronized frame indices between client and server
- ReconcilableState: Base class for networked entities (players, NPCs, projectiles)
- RollbackBuffer: Stores historical states for time-travel during reconciliation
For detailed architecture documentation, see ARCHITECTURE.md.
The plugin includes a complete working example demonstrating all features:
A minimal multiplayer game showing:
- Player spawning and movement
- Client-side prediction
- Server reconciliation
- Frame synchronization
- Input handling
Run the example:
- Open
addons/rollback_netcode/examples/simple_game/project.godot - Configure Run Instances (Debug > Customize Run Instances):
- Enable 3 instances
- Instance 1:
--server --preview - Instance 2:
--client=1 --preview - Instance 3:
--client=2 --preview
- Press F5 to run all instances
For a detailed walkthrough, see examples/simple_game/README.md.
- QUICKSTART.md - 5-minute integration tutorial
- ARCHITECTURE.md - Deep dive into system design and algorithms
- API_REFERENCE.md - Complete class and method documentation
- examples/simple_game/README.md - Example walkthrough
Network behavior is configured via NetworkSettings Resource files:
- Right-click in FileSystem panel
- Select "New Resource..."
- Choose "NetworkSettings"
- Save as
network_settings.tres - Edit properties in Inspector
@export var server_port := 4433
@export var max_client_count := 4
@export var rollback_buffer_duration_sec := 1.5
# Preview mode (editor testing)
@export var is_preview_mode := false
@export var preview_client_count := 2
# Performance
@export var tracking_perf := falseLoad configuration in code:
var config := load("res://network_settings.tres") as NetworkSettings
var netcode := NetworkOrchestrator.new(config, logger, time_provider)For all configuration options, see the NetworkSettings class documentation in API_REFERENCE.md.
The plugin includes 80+ unit tests covering core networking infrastructure:
In Editor (GUT Panel):
- Open GUT panel (bottom dock)
- Navigate to
addons/rollback_netcode/test/ - Click "Run All"
Command Line:
# Run all plugin tests
godot --headless -s --path . addons/gut/gut_cmdln.gd \
-gdir=res://addons/rollback_netcode/test/unit -gexit
# Run specific test file
godot --headless -s --path . addons/gut/gut_cmdln.gd \
-gtest=res://addons/rollback_netcode/test/unit/test_rollback_buffer.gd \
-gexit- Core Infrastructure: CircularBuffer (47 tests), ArrayPool (13 tests), RollbackBuffer (20 tests)
- Networking: FrameDriver, ReconcilableState, FrameSynchronizer
- Total: 80+ tests ensuring production reliability
- Network tick rate: Fixed 60 FPS (16.67ms per frame)
- Render framerate: Uncapped (runs independently)
- Rollback overhead: Sub-millisecond for typical state sizes
- Depends on state size and replication frequency
- Typical player state: ~100-200 bytes per frame
- At 60 FPS: ~6-12 KB/s per player
- ArrayPool reduces GC allocations from state snapshots
- Rollback buffer: ~90 frames × state size (default 1.5 seconds)
- Configurable via
rollback_buffer_duration_sec
Enable PerfTracker in NetworkSettings to monitor:
- Frame processing times
- Network packet rates
- Rollback frequency
- Buffer utilization
Ready to get started? Check out QUICKSTART.md for a 5-minute integration guide, or dive into the examples/simple_game/ for a complete working example.