GregOrigin - Rollback Core Pro: Accessible Netcode Framework for Fighting & Platform Games

Initial video (v0.2) | ✍🏼Read the manual. | 💬 Discord support. | 🎁 Get the Core version on GitHub: a functional open-source variety that I recommend you try before buying the Pro version. | 👨‍💼 Contact for custom integration / implementation.

🔥Say goodbye to input lag and latency in Unreal Engine! Introducing Rollback Core (Pro), the ultimate deterministic GGPO-style rollback netcode framework built specifically for UE5.

Whether you're building a fast-paced fighting game, a platform brawler, or a tight co-op experience, standard server-client networking just doesn't cut it. Rollback Core flips the script: simulate locally, predict remote inputs, and seamlessly re-simulate history when the truth arrives late. The result? Zero perceived input lag for your players. ⚡️🎮

✨ Why Choose Rollback Core?

🔹 Auto State-Saving (No Code Required): Forget writing complex C++ serializers. Just check the standard SaveGame flag on any Blueprint variable, and we'll automatically handle snapshots, transforms, and velocities via reflection. 💾

📖 Custom UDP Transport: Highly-optimized netcode featuring per-frame input redundancy, reliable ACKs, and built-in latency/packet-loss simulation for effortless stress testing. 📡

💬 Deterministic Fixed-Step Logic: Decouple your visual framerate from your game logic! Runs a perfectly rigid, predictable simulation under the hood. ⏱️ 👀 Visual Frame Debugger: Spawn our intuitive debugger right into your world to scrub through frames, view prediction ghost trails, and analyze rollback markers in real-time. 👻

👇 Seamless Matchmaking: Full OnlineSubsystem support so your players can effortlessly advertise, query, and join sessions out-of-the-box. 🤝

👾 3 Playable Demos Included: Learn by doing! We've included a fully playable 2D Viking Duel (with hitboxes & blockstun), a Network Packet-loss stress test, and a Basic Prediction environment. ⚔️

🛡️ Guided Editor Wizard: Get set up in 5 minutes with the onboarding Wizard. It automatically fixes project settings and injects the necessary rollback components directly into your existing Pawn. 🪄

🚀 Ready to upgrade your netcode?


Disclaimer: this plugin assumes a working knowledge of UE5 workflows, editor tooling, asset setup and so on. Custom integration, extension or modification may also require comfort reading and writing C++. If you are new to UE5 or plugin-based development, expect a learning curve. Before purchasing the Fab version, it is recommended that you explore the open-source GitHub version and the online manual first to understand the architecture, setup requirements, and integration style. This will help you determine whether the plugin fits your project and experience level.

Launch video:

Can it be used for a 3D fighting game in the likes of Tekken?

Hi there. It can, in fact 2 of the basic demos that come with it are fully 3D. And I’ll make more demos in the future.

1 Like

0.2.0, 2026-06-16 :wireless:

Networking correctness pass for peer identity and disconnect handling,
driven by reported issues with the Rollback.Net* console
workflow. Contains a UDP wire-protocol change (packet
version 1 → 2): all participants must run this build to interoperate.

Changed

  • :shield: Wire protocol v2. Every UDP packet header now carries a
    SenderPlayerId field and PacketVersion is bumped 1 → 2. Mismatched
    versions are rejected (never misparsed), so v2 peers cannot talk to v1
    peers. Ship all participants on this version.
  • Rollback.NetClient argument semantics. The 4th arg is
    now this client’s own PlayerId, announced to the host, instead of
    the remote peer’s id. The host now identifies the client by it, so
    Rollback.NetDisconnect <id> / Rollback.NetPeers can reference it.
    Rollback.NetConnect still takes the remote peer’s id. Help and
    usage text updated.
  • Peers now learn each other’s PlayerId from the handshake header on
    any packet (including Hello), instead of only from received input
    frames. An id set explicitly via ConnectToPeer is never overridden.
  • Rollback.NetHost now announces a host identity (LocalPlayerId = 0).
  • Rollback.NetClient now opens a single connection. It previously both
    auto-connected (via StartUdpPeer with RemoteHost set) and called
    ConnectToPeer, creating two peer records for the same endpoint.
  • URollbackNetSubsystem::ConnectToPeer is now idempotent per endpoint:
    reconnecting to an already-connected endpoint refreshes that peer (and
    promotes its id) instead of adding a duplicate record.
  • URollbackNetSubsystem::DisconnectPeer now returns bool (was
    void): true when a matching peer was found and removed.
  • URollbackNetworkBlueprintLibrary::DisconnectRemotePeer Blueprint node
    now returns bool. This adds an output pin; existing graphs that
    ignore it are unaffected.
  • Rollback.NetDisconnect logging is now accurate: it reports remaining
    peers from GetAllPeerInfo() (consistent with Rollback.NetPeers) and
    prints “No connected peer with PlayerId=N” when nothing matched,
    instead of always claiming success.

Added

  • FRollbackTransportConfig::LocalPlayerId (default -1): this peer’s
    own id, announced in every packet header. -1 preserves the previous
    behaviour of learning ids from input frames.
  • FRollbackTransportConfig::DisconnectCooldownSeconds (default 3.0):
    after an explicit DisconnectPeer, the endpoint cannot be
    auto-re-accepted for this window.
  • Automation tests: RollbackCorePro.Network.PeerDisconnectStaysGone,
    .PeerIdentityHandshake, .ConnectEndpointDedup, .DisconnectReturn.

Fixed

  • Disconnected peer immediately reappearing. DisconnectPeer removed
    the peer, but the still-running remote’s next packet hit the
    auto-accept path and re-created it with reset counters. A per-endpoint
    cooldown now prevents resurrection.
  • Rollback.NetDisconnect <id> doing nothing yet reporting success
    for console-connected peers. The host never learned the peer’s id (it
    stayed -1), so the id never matched. Header identity + accurate
    logging fix this.
  • Duplicate peer record on the connecting client. Connecting with an
    explicit id produced two records for the host endpoint (one -1, one
    the id); the -1 record received all traffic and showed real
    RTT/counters while the id record sat idle. Single-connect + endpoint
    dedup fix this.
  • Rollback.NetDisconnect “Remaining peers” disagreeing with
    Rollback.NetPeers
    for unassigned (-1) peers: the two commands
    counted different collections. Both now read GetAllPeerInfo().
  • Flaky RollbackCorePro.Network.PeerDisconnect automation test (it
    asserted connectivity before the receiving subsystem had pumped the
    handshake) made deterministic with a pump loop.

Build / verification

  • Compile-validated clean on UE 5.5, 5.6, and 5.7 via rcp_assemble.ps1; full suite green on 5.7 (15/15).
  • Per-engine staging regenerated for 5.5 / 5.6 / 5.7. The Blueprint DisconnectRemotePeer return-bool change landed afterward and is source-only.

0.2.0a update, 2026-06-16

Added

  • URollbackNetSubsystem::OnPeerReconnected (BlueprintAssignable): fired when a previously-known endpoint is auto-accepted again after a timeout, carrying the restored PlayerId and endpoint. Additive; lets UI distinguish a transient reconnect from a brand-new connection.
  • Rollback.NetJoinNull [Index=0] [LocalPlayerId=1] [LocalPort=0] and Rollback.NetSessions console commands. These complete the console-driven Null-LAN matchmaking loop in a packaged build: a host advertises (Rollback.NetHost), a second instance discovers (Rollback.NetFindNull), lists results (Rollback.NetSessions), and joins (Rollback.NetJoinNull), which brings up the UDP transport (announcing its own id) and connects to the advertised host endpoint. Previously JoinPlatformSessionByIndex was only reachable from the editor Setup Wizard.

Fixed

  • Timed-out peer reconnecting as a fresh PlayerId=-1. When a peer
    went quiet long enough to time out (CheckPeerTimeouts) and then
    resumed sending, the auto-accept path re-created it as a brand-new
    -1 record with reset counters, so OnPeerDisconnected (“Peer timed
    out”) was immediately followed by Rollback.NetPeers showing a
    connected -1 peer with recent activity, which looked contradictory.
    A timeout (unlike an explicit kick) now records the endpoint’s
    PlayerId; the returning peer is re-accepted as the same peer with
    that id restored and fires OnPeerReconnected instead. The explicit
    DisconnectPeer cooldown path is unchanged (kicked peers stay gone).
  • Disconnected peer immediately reappearing. DisconnectPeer removed
    the peer, but the still-running remote’s next packet hit the
    auto-accept path and re-created it with reset counters. A per-endpoint
    cooldown now prevents resurrection.
  • Rollback.NetDisconnect <id> doing nothing yet reporting success
    for console-connected peers. The host never learned the peer’s id (it
    stayed -1), so the id never matched. Header identity + accurate
    logging fix this.
  • Duplicate peer record on the connecting client. Connecting with an
    explicit id produced two records for the host endpoint (one -1, one
    the id); the -1 record received all traffic and showed real
    RTT/counters while the id record sat idle. Single-connect + endpoint
    dedup fix this.
  • Rollback.NetDisconnect “Remaining peers” disagreeing with
    Rollback.NetPeers
    for unassigned (-1) peers — the two commands
    counted different collections. Both now read GetAllPeerInfo().

Optional map (Content/Maps/RollbackNetDemo) for the available 2-Peer UDP Demo:

RollbackNetDemo.umap (20.8 KB)
DefaultEngine.ini (601 Bytes)

Please note that the plugin is still 0.2.0: not recommended for live production games yet. It’s robust, but still “early access” till indicated otherwise.
As always, liberal experimentation with the open source core is recommended at this point. :microscope:

0.2.2 update, 2026-06-18 :chequered_flag:

:video_game: Matchmaking — async Blueprint nodes, configurable search timeout & examples

A Blueprint-first matchmaking pass: the previously hidden session-search timeout is now configurable and readable, and the Find / Host / Join flow is exposed as Advanced-Sessions-style latent nodes with example assets. Additive with no API breaks.

Legend: :sparkles: new Blueprint node · :plus: new API · :counterclockwise_arrows_button: changed · :white_check_mark: tests · :memo: docs · :wrench: tooling · :snake: Python · :puzzle_piece: example asset

:stopwatch: Configurable session-search timeout

  • :counterclockwise_arrows_button: URollbackNetSubsystem::FindPlatformSessions no longer hard-codes a
    10.0f search timeout; it reads a configurable value, so callers can size
    their own “Searching…” watchdog/UI to the real search instead of guessing.
  • :plus: SessionSearchTimeoutSeconds (EditAnywhere, default 10s, ClampMin 0.1)
    plus GetSessionSearchTimeoutSeconds() (BlueprintPure) and
    SetSessionSearchTimeoutSeconds() (BlueprintCallable, clamps to 0.1).

:satellite_antenna: Results-carrying completion delegates

  • :plus: OnFindSessionsComplete(bool, TArray<FRollbackMatchmakingResult>, FString); hands back the whole session list in one shot when a search finishes.
  • :plus: OnCreateSessionComplete(bool, FName SessionName, FString).
  • :plus: OnJoinSessionComplete(bool, FString); fires after the UDP transport
    actually connects on a successful join (kept in lock-step with the generic
    OnMatchmakingComplete via an internal BroadcastJoinComplete helper).

:sparkles: Async / latent matchmaking nodes (the Find / Host / Join trio)

  • :sparkles: Find Rollback Sessions (Async); URollbackFindSessionsAsync: runs a
    search, waits for completion (bounded by the timeout), delivers the list on
    On Found / On Failed. Optional Timeout Seconds pin (-1 = use configured).
  • :sparkles: Host Rollback Session (Async); URollbackCreateSessionAsync: brings up
    the UDP transport on Host Port if needed, advertises the session →
    On Hosted (SessionName) / On Failed.
  • :sparkles: Join Rollback Session (Async); URollbackJoinSessionAsync: joins a Find
    result and waits until the transport connects → On Joined / On Failed.
  • :plus: Pure helpers FindBestRollbackSession (lowest ping with an open slot) and
    FormatRollbackSession (one-line summary) on URollbackNetworkBlueprintLibrary.

:puzzle_piece: Example actor & Blueprint generator

  • :puzzle_piece: ARollbackMatchmakingExampleActor (Blueprintable) wires all three nodes
    into one actor with editable defaults (Match Id, LAN, port, timeout, auto-find)
    and OnSessionsFound / OnHosted / OnJoined / OnError events for UI.
  • :snake: Content/Python/generate_matchmaking_examples.py; run in-editor to create
    /RollbackCorePro/Examples/BP_RollbackMatchmakingExample (a ready-to-drop
    subclass of the example actor).

:white_check_mark: Tests

  • :white_check_mark: New automation tests: RollbackCorePro.Matchmaking.FindSessionsCompleteDelegate,
    .FindSessionsAsyncNode, .FindSessionsAsyncNodeFailure,
    .HostSessionAsyncNodeFailure, .JoinSessionAsyncNodeFailure.
  • :white_check_mark: Added URollbackMatchmakingTestSink, a reflected UObject that captures the
    dynamic-delegate / node-pin payloads tests assert on.
  • :counterclockwise_arrows_button: RollbackCorePro.Network.NullMatchmakingConnect now derives its poll window
    from GetSessionSearchTimeoutSeconds() instead of a magic 12.0 constant.

:memo: Docs

  • :memo: HTML manual: new delegate rows, an async-node table (Find/Host/Join), the
    pure helpers, the example-asset + Python-generator instructions, and an updated
    client-flow snippet showing the obtainable timeout.

:wrench: Project / tooling

  • :wrench: Enabled PythonScriptPlugin in RollbackCorePro.uproject (required to run
    the example generator).

:hammer_and_wrench: Build / verification

  • :hammer_and_wrench: Clean on UE 5.5 - 5.7; RollbackCorePro.Matchmaking automation suite 6/6
    green
    ; the Python generator verified to produce the example Blueprint asset.

A 2-peer demo in action, version 0.2.2+

0.2.2a update, 2026-06-20 :up_arrow:

🎮 UMG matchmaking menu example

  • 🧩 URollbackMatchmakingMenuWidget (with row widget URollbackMatchmakingMenuRow): a fully native UMG menu (no .uasset required): Host / Find buttons and a scrollable list of found sessions, each with a Join button. It builds its own tree in RebuildWidget, drives the Find / Host / Join async nodes (mirroring ARollbackMatchmakingExampleActor), and exposes config (Match Id, LAN, port, timeout, …) plus OnHosted / OnJoined / OnSessionsFound / OnError events. Subclass it as a Widget Blueprint to restyle: the behaviour stays in C++.
  • Rollback.ShowMatchmakingMenu: creates the menu and adds it to the viewport (running game / PIE).
  • 🧩 The example generator now also emits /RollbackCorePro/Examples/WBP_RollbackMatchmakingMenu (a Widget Blueprint subclass of the menu widget).

🖥️ Console-command parity for the async Host/Find/Join flow

  • Rollback.Host [MatchId] [Port=7777] [Slots=2] [LAN=1], Rollback.Find [MatchId] [Max=20] [LAN=1] [Timeout=-1], and Rollback.Join [Index=0]: drive the same URollbackCreateSessionAsync / URollbackFindSessionsAsync / URollbackJoinSessionAsync nodes the Blueprint flow uses, for console/headless testing parity. Rollback.Join joins a result cached by a prior Rollback.Find. (Previously the async flow was Blueprint-only; the existing Rollback.Net* commands call the subsystem directly.)
  • URollbackNetConsoleSink: a small UObject that binds the async nodes' dynamic result pins (which cannot bind lambdas), logs each outcome, and self-releases.

🔧 Editor: one-click example generation

  • 🔧 Generate Example Content on the Rollback toolbar combo (new Examples section) and Generate Example Blueprints on the Setup Wizard's Integration page run the bundled generator via IPythonScriptPlugin (FRollbackCoreProEditorModule::GenerateExampleContent() → returns whether it ran), degrading gracefully with an on-screen note when the Python Editor Script Plugin is unavailable. The wizard reflects the real outcome in its toast and Finish-page summary.
  • 🔧 RollbackCoreProEditor now privately depends on PythonScriptPlugin, and the plugin descriptor enables it.
  • 🐍 generatematchmakingexamples.py extended to also author the WBP menu via WidgetBlueprintFactory.

✅ Tests & verification

  • ✅ New automation tests: RollbackCorePro.Matchmaking.ConsoleSinkHostFailure, .ConsoleCommandsRegistered, RollbackCorePro.UI.MatchmakingMenuRowJoin, .ShowMatchmakingMenuRegistered.

Rollback P2P demo. Edit the file to use your own paths. (Powershell scripts are not allowed in Fab builds.)

README.md (4.3 KB)
RunRollbackP2PDemo.ps1 (3.7 KB)

0.3.0 update, 2026-06-23 :roller_skate:

Rollback correctness & netcode pass: fixes the core replay off-by-one, completes
state restore (velocity / angular velocity / CharacterMovement), and upgrades desync
detection from a local replay check to genuine cross-peer checksum exchange
(auto-wired). Contains a breaking UDP wire-protocol change (packet version 2 → 3):
all peers must run this build to interoperate.

Legend: :bullseye: correctness · :shield: hardening · :globe_with_meridians: networking · :ice: physics/CMC · :plus: new API · :sparkles: new component · :counterclockwise_arrows_button: changed · :warning: breaking · :white_check_mark: tests · :hammer_and_wrench: build/verify · :memo: docs

:bullseye: Rollback correctness

  • :bullseye: Off-by-one double-application fixed. SimulateFrame now snapshots the
    start-of-frame state before ticking, so RollbackToFrame(F) restores
    StateBuffer[F] and replays from F applying the target frame’s input exactly
    once
    . Previously the snapshot was taken after the tick, so every rollback
    re-applied the corrected frame twice and drifted by one frame of its motion. (The
    prior tests used all-neutral input, where the double-apply was invisible.)
  • :white_check_mark: RollbackCorePro.Rollback.NoOpReplayIsIdentity: a no-op rollback (identical
    recorded inputs) must reproduce the exact pre-rollback state.

:globe_with_meridians: Cross-peer desync detection: was local-only

  • :warning: BREAKING: wire protocol v3. New StateChecksum packet type; PacketVersion
    bumped 2 → 3. Mismatched versions are rejected (never misparsed), so v3 peers
    cannot talk to ≤ 0.2.2 (v2) peers. Ship all participants on this build.
  • :plus: Genuine cross-peer detection: peers exchange per-frame state checksums and
    compare each against their own; a true mismatch calls RecordDesync() and broadcasts
    OnDesyncDetected(Frame, peer, delta). Previously the “desync detector” only compared
    an entity’s own pre/post-rollback checksums locally (a replay-determinism check) and
    could never observe two machines diverging.
  • :plus: Auto-wired: URollbackManager records and (on an interval) sends the
    confirmed-frame checksum automatically while transport is connected — the demos
    inherit it for free. New API: RecordLocalStateChecksum, SendStateChecksum,
    ComputeStateChecksum (order-independent XOR aggregate), GetConfirmedFrame /
    GetConfirmedFrameForPlayer.
  • :counterclockwise_arrows_button: Confirmed-frame policy: only frames whose inputs are all in from every peer
    (highest contiguous received input) are checksummed, so the state is final and a
    mismatch is a real desync: no false positives from in-flight prediction.

:ice: State-complete physics / CharacterMovement rollback

  • :wrench: Velocity is now restored on rollback (it was saved but never re-applied).
    Physics roots get SetPhysicsLinearVelocity; every entity also surfaces it via
    LastRestoredVelocity and the new OnRollbackStateLoaded(Frame, Velocity) event so
    custom/kinematic movement can re-apply it.
  • :ice: Full rigid-body + CharacterMovement state captured/restored. The snapshot gains
    angular velocity and CMC MovementMode/CustomMovementMode; save/load now restore
    linear + angular physics velocity and CMC velocity/movement mode. Surfaced via
    LastRestoredAngularVelocity.
  • :sparkles: URollbackCharacterMovementComponent: a UCharacterMovementComponent subclass
    driven by the rollback loop (its own engine tick disabled); the state component calls
    its RollbackStep(dt) once per fixed frame for both live and replayed frames.
  • :warning: Determinism boundary unchanged: restore is now correct and complete, but
    cross-machine forward-sim determinism (collision / Chaos) is not guaranteed: use
    flat/kinematic movement or a deterministic mover where that matters.

:shield: Robustness

  • :shield: Rollback to an evicted/missing frame now aborts cleanly instead of replaying
    forward from the live state and corrupting the buffer. RollbackToFrame no-ops (no
    state change, no rollback counted) when no entity holds the target frame’s snapshot;
    usable rollback depth is bounded to MaxBufferSize snapshots per entity.

:white_check_mark: Tests & verification

  • :white_check_mark: 12 new automation tests (Rollback.NoOpReplayIsIdentity,
    Rollback.MissingFrameAborts, State.VelocityRestored,
    State.AngularVelocityRestored, State.CharacterMovementRestored,
    State.ChecksumDeterministic, State.ChecksumOrderIndependent,
    Network.CrossPeerChecksumDesync, Network.ConfirmedFrameTracking,
    Network.ManagerAutoChecksum, Movement.RollbackStepSafe,
    Movement.CMCDrivenByRollbackTick). Full RollbackCorePro suite 40/41 green (the
    two-process-only Network.NullMatchmakingConnect fails single-process by design).
  • :hammer_and_wrench: Two-process packaged P2P session verified: Null OSS matchmaking + UDP
    transport + the new v3 StateChecksum traffic ran ~1440 frames with both peers
    connected, no desync false positives, and no transport/parse errors.

Updating the manual to 0.3.0 (online & PDF) will take a few days, until then these features are undocumented. Thanks for your patience. :folded_hands:

1 Like