I am working on an RTS style game with movement and attack behaviors that look and feel like Starcraft2. The main deviation in terms of the mechanics is I want units to always end up stopping on a position in a grid. With that said, I don’t want the units to actually move along Up/Down/Left/Right grid directions, just that they always stop on a grid point. I also don’t want any two units to settle on the same grid (unless they are just temporarily passing through to get to their target).
A good reference for this is the game “Tooth and Nail”. The units move freely but always end up in a grid with no other units occupying the same grid position. Here’s a link to a video of the desired behavior: Watch Grid_edited | Streamable
The thing I don’t want is that in Tooth and Nail units don’t have any collision between each other. I’d like units to still have RVO style avoidance behavior and for players units to be able to block enemy units from moving past a narrow area if for example you fill all the grid spaces in the gap with units. But if they are ally units, ideally you can walk through and the units just nudge aside visually for a second.
I am currently using a grid-graph with the FollowerEntity component for the movement so far. But happy to switch to whatever makes sense!
I’m assuming I’ll need to write a good chunk of custom logic for this to work. But not sure what configuration on the plugin to use to set myself up for success!
This will pick the closest node center to the given point.
Note that it may be tricky to prevent units from getting stuck in this case. What you will likely need to do is to detect if a unit has reached its destination, and if so, lower its RVO priority to allow other units to more easily push it around.
Thank you for the help Aaron! Quick Follow-up, is there a way with the tool today to make sure that no two units occupy the same gridspace?
Ideally if the space their destination is set to is occupied they’d stop at the nearest empty space. Will I need to write custom logic to determine if a space is occupied and find the nearest space myself and update the ai.destination? If I go down this route, would you recommend I just have my own grid independent of the actual grid for the pathfinding?
And after setting the RVO priority to be low, and the unit does get pushed, is there a way to make sure they always try to go back to the gridspace after being pushed aside temporarily?
There’s an (aptly named) priority setting that may help here! You can also change the collidesWith and layer settings for granular control of who interacts with who.
You can subclass the NNConstraint class and override the Suitable method. Then check if the node is occupied there. When passing your custom NNConstraint to the AstarPath.GetNearest method, it will automatically use it to find the nearest suitable node.
The AIPath/RichAI movement scripts have an attempt at this behavior using the RVODestinationCrowdedBehavior class (enable “Stop When Destination Is Crowded” in the AIPath/RichAI inspectors). It is used in the included (wip) RTS example scene. It has an awful lot of hard-coded magic constants, though. So I don’t think it was the right approach for a general behavior. Could work well for some games, though. It was designed to work similarly to how Starcraft 2 works.