What is the "correct" way for AI to follow a path?

I’m currently working on some pathfinding and simple AI stuff to get a handle on this. I have a 2D grid based game and I’ve implemented my own pathfinding logic in C++. I’ve set up a basic behaviour tree and blackboard and I’m in the middle of creating a simple BTTask that picks a random position on the map and moves to it. My first impulse was to select the position and do the pathfinding from ExecuteTask. Then, in TickTask, I would get the path and move the actor toward the next path node using SetActorLocation, removing nodes from the path list as I go.

Digging around through the code, I’m getting the feeling that this is the “wrong,” way to do it. Similar tasks seem to simply tell the actor where they’re going and wait for the actor to inform them that they’ve finished (or failed). The logic for all of this is also spread all over the place, with the AIController, Nav system, and PathFollowingComponent (and probably some movement component in there somewhere too) all doing a bit of the work.

My question is what is the UE4 “correct” way of doing this? Do I really need to create my own inherited version of the path follow component? Should the AIController (or maybe the pawn?) be responsible for managing and driving all of this? Something else entirely?

In UE4, if you can use the navigation system, you should absolutely use the navigation system. It is optimized, it has good tooling, and it can adjust to actors of different capabilities (take elevators, different sizes, etc.) It also integrates with real-time “avoidance” in crowd scenes. (“Detour”)

As you have noticed, the Character pawn type and the AI system integrate with Navigation already, so it’s pretty easy to make it “go to the place.” You may also want to look at the AI state machine tutorials for how to control characters without necessarily writing code or even executing some particular task every tick.

There are some gameplay cases where you can’t use Navigation – path planning that uses time-based node reservation (as you’d have in an advanced RTS, say) would be hard to do on top of basic Navigation – but it doesn’t sound like that’s what you’re doing.

Generally, the AIController should figure out WHERE it wants to go, and tell the Pawn, and the Pawn should do the physical work of locomotion/animation.

1 Like

Thanks for the reply.

There are a bunch of reasons why I’ve gone the direction I have, but I’m happy to be swayed in a different direction if I’ve made the wrong choice.

For navigation/pathfinding, I have a simple 2D grid. Tiles in that grid can either be walkable or not, at the moment, but in the future there will be different weights on the tiles (e.g. moving through water is slower and will cost more). Implementing my own A* function gives me tighter control with a system that should be fairly lightweight. If I can do the same thing with the nav system (and more importantly, if there are examples of how to do something similar), I’m not averse to that.

For movement itself, I have comically simply characters. If you’ve seen Rimworld or Prison Architect, it’s the same thing i.e. static sprites that just move around. For this reason, I have no movement component and I’m using a pawn rather than a character. That’s possibly a bit off topic, but worth stating.

For path following, I actually wasn’t able to track down exactly where the pawn movement itself occurred using the nav system. MoveTo starts it off and puts the request into the nav system, but I was never able to figure out where the actual movement was handled. I did a search for every instance of SetActorLocation in the solution and that didn’t turn up anything, so it must be done in some other way. It was at this point that I came here to make this post, as I felt I might be missing something core.

The general advice of the role of the controller and the pawn is useful. Thanks.

Finally, can you point me to any state machine tutorials that you think would be useful? To be clear, I fully understand what an FSM is and how it works but I have no idea how they function in UE4 and a quick Google search is only bringing up videos that explain the concept of FSMs rather than any implementation.

Thanks again for your time.

After doing a bunch of digging, I was able to find more information of using the nav system. It’s actually quite easy to implement your own pathfinding while still integrating with the nav system. The following two links say essentially the same thing and will walk you through how to implement a custom pathfinder. It’s essentially just one function, although one thing that these articles don’t mention is that you’ll also need to override the ProjectPoint function. Very straightforward.

https://ue4community.wiki/legacy/replacing-the-pathfinder-h6eyeor0#code-example-based-on-arecastnavmeshdata

From there, I used a UFloatingPawnMovement (but you can use whatever makes sense for your game) to handle the movement and everything else was pretty much automatic.