Hi Aron, long time no visit!
I’m using A* Pathfinding Project Pro for a multiplayer top-down game and wanted to ask whether you would consider supporting a somewhat different local-avoidance movement model, or whether there is already a lower-level API that might be suitable.
I currently use A* very successfully for pathfinding, and I have also experimented quite extensively with the RVO/local avoidance system. However, I’ve concluded that even though its clearly very optimised, the standard RVO movement model is too advanced and not a particularly good match for the way I need characters move in my game.
My NPCs deliberately behave much more like player-controlled characters (with the limitations that traditional input systems bring) than conventional continuously-steered AI agents.
Their movement has the following constraints:
- Characters move at fixed speeds: essentially walk or run.
- There is no meaningful acceleration/deceleration model.
- Characters should normally continue at their selected walk/run speed rather than slowing down to avoid each other.
- Movement is restricted to eight directions: the four cardinals plus four diagonals.
- Characters smoothly rotate visually between those directions, but their actual movement direction is discrete.
- NPCs and human-controlled players are intended to look broadly similar in how they move.
- Local avoidance should therefore look like a person making a small deliberate course correction, rather than a continuously adjusting crowd agent.
For example, if two characters are walking towards each other, the behaviour I would ideally like is something similar to:
- Detect the likely collision reasonably early.
- Prefer one side, e.g. a slight/right-hand passing bias.
- Temporarily move in the adjacent diagonal/cardinal direction.
- Continue at normal walking speed.
- Once sufficient clearance has been created, return towards the original route.
The resulting movement would look more like a brief sidestep than a continuous RVO velocity adjustment.
My understanding is that RVO fundamentally calculates a preferred continuous velocity: both a direction and a speed. That makes a lot of sense for conventional agents, but it creates a mismatch for my movement model.
For example, RVO may decide that the best early response to another agent is:
- continue almost in the same direction,
- but reduce speed slightly.
My NPC cannot really apply that result because slowing from, say, 100% speed to 90% speed is not part of its movement model.
If I ignore the speed reduction, the next RVO result may eventually become a more significant directional change when the agents are much closer together. This can make the avoidance appear to happen late.
Likewise, an RVO result containing an arbitrary direction cannot be followed directly because the NPC is restricted to eight valid movement directions.
I currently use RVOController more like a collision-warning system than a movement controller.
I have tried calling SetTarget, obtaining the result from CalculateMovementDelta, inspecting the proposed movement direction / calculated speed, then convert that result into one of my eight legal movement directions and move the character myself at its fixed walk/run speed.
In practice this means that a subtle RVO suggestion can become a full 45-degree direction change. I have experimented with thresholds, time horizons, temporary commitment to an avoidance direction, route deviation checks, etc.
It works, but I increasingly feel that I am effectively translating one movement model into a very different one, and much of the value of the RVO solver gets lost in that translation.
I am wondering whether there could be value in exposing an avoidance mode/API that separates collision prediction / avoidance intent from the final continuous velocity solution.
For example, information such as:
- whether another agent is currently on a meaningful collision course,
- estimated time until closest approach/collision,
- predicted closest separation,
- which neighbouring agents are responsible,
- suggested passing side,
- how urgent avoidance currently is,
- or an avoidance direction independent of a desired speed.
This would allow a game-specific movement controller to make its own constrained decision.
Another potentially useful approach could be allowing the RVO solver to work with a constrained set of acceptable velocities, for example:
- fixed magnitude,
- only a small set of allowed direction vectors,
- no deceleration except stopping,
- or user-supplied candidate velocities.
In my case the candidate velocities might effectively be North, North East, East etc. all multiplied by either the current walk or run speed.
The avoidance solver could then evaluate those candidates rather than selecting an arbitrary velocity from a continuous range.
In my server-authoritative multiplayer game, NPC movement is simulated on the server and replicated to clients. That makes deterministic and relatively simple movement particularly useful. I would prefer to keep the same discrete movement rules for NPCs that are used by player-controlled characters. The game may have many NPCs active, so efficiency is still important, but the avoidance requirements are relatively local and simple compared with a general crowd simulation.
Would this kind of constrained local avoidance be something you would consider supporting?
Alternatively, is there already a lower-level part of the RVO API that would be more appropriate for this use case? I noticed that internally the RVO implementation appears to have concepts such as allowed velocity deviation angles, so I wondered whether there may already be functionality closer to this than what is exposed through RVOController.
Even if this is outside the intended scope of RVO, I’d be interested in your opinion on whether using A* for pathfinding while implementing a separate simple local-avoidance layer would be the more appropriate architecture for this sort of character movement.
Thanks for reading, and any advice is greatfully received!