Advice for Networking and Navigation with Obstacle Avoidance in a Multiplayer RTS games?

Godot Version

4.5.1

Question

How do I keep unit paths synchronized across clients for multiple units in a multiplayer RTS game? Specifically, for when paths need to be changed because of obstacles.

Currently, I just mutate my A-star node, turning points off and on again in each units local vicinity. So when a unit gets blocked, it checks for obstacles in it’s local area, adjusts the A-star node accordingly, and then repaths.

This is happening mid-tick and each unit would then mutate their own instructions, which recently I’ve learned is sort of bad to do :frowning: .

To fix this, I plan on making units either set a flag or signal that they need a path change and then have each client update these paths on tick, rather than mid tick like they currently do.

However, to avoid obstacles, should I be using this solution of turning nodes on and off for Astar? I’m thinking of maybe making a “gridmanager“ node, that records and refreshes occupied tiles per tick and use that instead?

Below is a gif of the problem in action. The slimes just completely de-sync across my clients, and I’m not really sure if the fix of getting paths recalculated on tick rather than mid tick would actually fix this issue.

GIF 12-18-2025 6-24-06 PM

The obstacle avoidance works “okay” with less units or with just 2 units bumping into each other, but it’s not really good enough. It will sometimes de-sync in these scenarios as well; see below.

GIF 12-18-2025 6-53-03 PM

Some context about game I’m making:

  • Old-school in terms of it’s grid, 1 tile is the size of 1 unit, and units move only left-right-up-down.
  • I don’t intend to support a large number of units on screen, maybe 100+ max.

Another option I’m looking into is something more rule based? “See if tile is occupied”, if yes, move left-right or up-down depending on the direction, and then repath. I imagine this would be much easier to sync in a multiplayer game, but would this sort of logic still work in larger scales like during a battle?

Oh also, I don’t think I would want to do a solution with physics; have units bump and slide past each other. Since this would require syncing physics simulations across clients. I’ve tried to do that a little bit before across clients and it was a total pain, so I want to keep any sort of physics simulation to a minimum in my game.

Any advice on the sort of structure I would need to implement would be much appreciated! :slight_smile:

Correct me if I’m wrong because I will be assuming some parts.

This desync problem seems to be a matter of who is calculating the paths. For multiplayer games it’s better to let the server calculate all the paths and positions and then serve these to the clients.

If every client tries to calculate the paths in real time it will have issues.

Let me know if this is the issue or it’s something else. Also adding some details on how you designed the multiplayer part would be good for understanding the issue.

2 Likes

Ah sorry; I’m not doing client-server, but peer 2 peer in lockstep. So all commands are buffered locally and sent to each player to be confirmed by all other players for the next tick.

But yes, each client is calculating their own path. I’m hoping by getting paths to be calculated on tick that this would help mitigate the issue. I’m not looking for perfect but something fairly consistent would be nice.

If having a “server“, or maybe in my case, a main authoritative player calculate paths. I could do that, it doesn’t sound too tricky to implement, but is it cheap to do? Will this introduce any other issues I should be aware of?

The design of my networking solution is probably a little janky, since I’m just trying to figure this sort of thing out from articles/books/websites. I’ve been looking around for good resources, but it’s hard to find exactly what I want in terms of designing a lockstep system for an RTS.

I have an abstract below that details the main structure I’m working with.

Please let me know if that helps or if you’d like any other details. Thank you!

Having peer-2-peer connections still requires at least one of the two clients to function as a server (ideally). Only one of them should be handling the simulation to avoid these sync issues. Implementing a server is not costly, make some tests. :smiley:

That’s my guess, try programming the pathfinding only in one side and then updating the position on the other client, without recalculating the pathfinding. Let me know if that solves it!

1 Like

I have this pretty much figured out now, and I thought to just give an update to what fixed at least one of the scenarios I was experiencing. There’s still a bit more work I need to do, but I should have it figured out when I have more time.

The key changes I made were:

  • Unique unit identifiers; units now have a synced unique ID. And this determines a consistent tick order.
  • No mid-tick mutations; so prevented state changes and intent changes mid-tick. All pathing, and tile interactions go through a centralized path and grid managers.
  • Fully tick-based movement; Movement is now entirely tick-based using integers. So units make discrete progress towards tiles and once completed it moves to the next tile. Visually there’s still some work I need to do, but it’s fine for now.

And yeah, that basically fixes the below scenario where two units bump into each other. Seems like everything is syncing fine.

The red tile is where the unit is actually occupying. Tile ownership is handled via the grid manager using a reservation system (reserve → leave → occupy).

And to get units to go around each other, I still do the same thing with Astar (turning nodes off and on), but I add a “random“ amount of time before continuing the path after repathing. This works cleanly with the grid manager for now, but I might need to refine later if I wanted to handle more units I imagine.

I did notice that if units move too fast then it’s possible for a de-sync to occur, so I’ll just keep the speed low for now until I can figure out why that would happen.

GIF 12-29-2025 1-55-09 PM

To fix the scenario with the slimes, I’ll have to make a few more manager classes and rework how unit vision works, but this should be fairly straightforward after figuring out this prior issue.

I’m just going to mark this reply as the solution since I don’t really need any more advice at this point.