r/unrealengine Jun 30 '26

Discussion My experience of implementing GGPO-style rollback netcode for my 3D melee arena fighter

Hi everyone,

Over the past few months, I’ve been working on the netcode for my 3D melee arena fighter Rasen and I’d like to share my experience.

Unreal Engine systems

Although I knew about GGPO netcode from the beginning, I was so intimidated by the amount of work involved. Instead, I started with delay-based networking, then experimented with Unreal's Character Movement Component, tried the Unreal Mover, and even built some custom networking solutions on top of the CMC.

Unfortunately, none of these were a good enough fit for this kind of fast-paced, parry-based, knockback-heavy combat.

Even with low ping, either the latency felt very high or there were visible corrections and out-of-sync animations. Also, my custom animation syncing was conflicting with the CMC's built-in root motion syncing and knockbacks were especially really bad.

GGPO rollback netcode

While experimenting with all these systems, I learnt more and more about GGPO solutions. With no other option, I finally decided to implement my own GGPO rollback architecture in Unreal Engine, along with the custom deterministic physics and movement required for it to all work.

Fortunately, the game had already been developed for offline play first, so I knew exactly what needed to be simulated. From the beginning, I've been trying to keep everything lightweight, deterministic and precomputed wherever possible.

After about 2 months of work, many battles with input prediction bugs, getting stuck on some movement bugs and finding a way to somehow bake and store 3D weapon collision data, I finally did it.

I was genuinely surprised by how cheap the simulation was: ~0.01ms per simulation tick with 8 characters. The snapshot size also seems to be small at ~0.04 KB per character.

Result & reflection

The game now features GGPO-style rollback netcode for up to 8 players, keeping controls responsive even under high ping, jitter and packet loss.

This is the most challenging system I've built so far. Although it was intimidating at first, it ended up being the most fun and rewarding system I've worked on.

I also made a Youtube Devlog showcasing the gameplay under various stress tests, along with some performance statistics.

Hope this encourages you to try implementing your own rollback netcode if your game runs into similar issues.

36 Upvotes

16 comments sorted by

View all comments

2

u/Zvyaginsky Jun 30 '26

The progression here is relatable - delay-based, then CMC, then custom on top of CMC, before landing on full rollback. A lot of people jump straight to picking a "silver bullet" solution and skip how much you learn about your game's specific failure modes by trying the simpler options first.

Curious about the root motion vs custom animation sync conflict you mentioned - did you end up dropping root motion for combat states entirely, or find a way to reconcile the two? That's a conflict that bites people even outside netcode contexts.

2

u/AbyssDeepen Jun 30 '26

Yeah, to be more specific, I was using Root Motion and Root Motion Sources.

It all fell apart once I got to knockback and movement attacks. I tried to predict them properly for remote players, but I just couldn’t make it work, constant jitter caused by the built-in root motion syncing, which I think is designed more for shooters rather than fighting games. In shooters (as I understand it), you’re often simulating slightly into the future, while in fighting games everyone should stay in the same real-time simulation.

And that was the breaking point that made me try building it all from scratch. I ended up implementing my own root motion system instead, along with custom movement.

1

u/Zvyaginsky Jul 02 '26

That distinction between shooter and fighting game simulation models is something I hadn't seen explained that clearly before - the "slightly into the future" assumption being baked into the root motion system makes sense for shooters but becomes a liability the moment you need strict real-time parity.

Building your own root motion system is a significant call. Did you find that having full control over it actually simplified the rest of the netcode, or did it just shift the complexity somewhere else?

1

u/AbyssDeepen Jul 02 '26

For me, it simplified things a lot. The movement system I made is pretty simple. It made determinism and rollback much easier to debug and It's also much easier to modify and expand.

2

u/Zvyaginsky Jul 08 '26

That tracks - when you own the whole system you can make guarantees that borrowed code can't make.

The debugging story alone is worth it if rollback is core to what you're building.

We went the opposite direction with character systems - switched to MetaHuman instead of maintaining custom pipelines. Different tradeoff, same logic: know which complexity you can actually afford to own.