Pathfinder: A pathfinding character control module for NPCs

While I was working with pathfinding NPCs, I noticed that some commonly used methods such as using Humanoid:MoveToFinished() in between waypoints makes the character stop or not follow a specific path in a lot of cases, and realised a need for a character control module which is easy to use, configurable, can follow a part/model or pathfind to a location once, and applicable for most cases. That is why I made Pathfinder, I first got the idea from an NPC character I was working on and decided to expand it to an open source module form.

The GitHub repository is the main source for all information related with this module and you can find everything there, plus lots of extras.

While the module is tested and the methods I used were used in a live game before, the module itself as a whole was not. If you experience any issues, please create an issue on the GitHub repository.

What does Pathfinder do?

  • Pathfinder uses PathfindingService for waypoints and waypoint actions, which means it supports every PathfindingService features Roblox offers.
  • Pathfinder uses custom logic (instead of MoveToFinished) to control the delays the character needs to follow the target, which can be a still or a moving target.
  • Pathfinder offers defaults which will be useful for most of the use cases, however, is designed to be configurable.
  • Pathfinder offers user-made actions for NPC characters (example, NPC can jump to the target player if the distance is less than an amount).

What does Pathfinder NOT do?

  • Pathfinder is not a replacement to PathfindingService. It actively uses PathfindingService to create the waypoints.
  • Pathfinder is not made for non-Humanoid or non-character (such as cars) entities. They might or might not work.
  • Pathfinder will not work as fast as non-pathfinding character control methods, such as the plain MoveTo.
  • Pathfinder will not add new waypoints, although it can skip some waypoints to move without stopping, which means your paths will be as good as your navigation mesh in most cases.

Example usage: (please check the GitHub repository for detailed examples and explanations)

local p = Pathfinder.new(char, {
    Target = t,

    AgentParameters = { --optional
        AgentRadius = 2, 
        AgentHeight = 5,
        AgentCanJump = true, 
        AgentCanClimb =  true,
        PathSettings = 
            {
                SupportPartialPath = true
            },
        Costs = {
            PathfindAvoid = 9999,
            Truss = 1
        }
    },
}) :: any

After this code I would just need to run it with p:Run().
This example does not demonstrate moving targets or the optional configurations, the rest is in the repository.

Installation

You can get the module from Creator Store here, for wally and manual installations please check out the GitHub repository.

Issues and suggestions

Before reporting any issues, please set DebugWaypoint = true on your Pathfinder instance ( DebugMode = true will also be helpful but if you have many NPCs, the prints might lag Studio) and make sure that the nodes are where you would expect them to be. You might need to adjust your agentParameters or you might need to check your NavigationMesh (File → Studio Settings → Studio → Show Navigation Mesh and enable) and optimize your environment for a more ideal NavigationMesh. If there is something unexpected with your Navigation Mesh, module’s accuracy might also be affected.

If you think that the issue is with the module after checking these, you can report the issues and suggestions to the repository to keep everything organized, however I’ll also respond to this topic.

14 Likes

Can this be used to make npcs attack ?

3 Likes

This looks so friggin good!, I readed the docs but i still don’t quite get how to make conditions, Because it just returns 1 value (but what if i need more conditions?)

Also, the Abilities Runs In a Sequence?

Yes it can. You can create a damage function with the callback it has. Maybe in a later release I should provide an extra module with action templates.

2 Likes

In the documentation it says this:

local PathfinderAbilities = {
    {
        ActivationRange = 30,
        ActiveTime = 3,
        CooldownTime = 10,
        CustomConditions = function(t)
            return true
        end, -- optional
        Callback = function(t)
            -- t.Character, t.Target and t.Distance are available
        end,
    }
} :: PathfinderAbilities

I assume you are talking about the CustomConditions function. The return needs to be a boolean but you can check for anything inside of the function. In this example it just returned true but this is optional, if you just want a distance check with cooldowns you don’t need to provide a function there.

They run randomly as of right now. Is there a reason why you want them in a sequence? I might add a customizable order for all abilities if there’s a good use case I didn’t think of.

2 Likes

i see

Is there a reason why you want them in a sequence?

Well, I am currently Doing a RPG Game, And i am doing bosses, so , it would be cool if you could add a Option to make the Abilities Randomized/Sequence type for patterns so players can memorize them

That makes sense, I’ll create a feature request on the repository and add it in a future release.

1 Like

Update v0.1.1

  • Added NoPathAction
  • Added support for random/sequenced abilities
  • ClosestNoPath now has the same actions with NoPath
  • Typing improvements
  • More tests

Update v0.2.0

  • Nothing new after v0.1.1 except fixing wally installation. This version is just to match the wally version. Versioning will be used wisely in this project, but I did not want to skip multiple versions.

This is so peak. Thank you.

Will you implement events in the future (something like PathReached or WaypointReached for example)? I’m having fun with implementing events on my own, but obviously that would improve workflow for some.

The approach was using the provided functions for such actions, basically eliminating the need of hooking separate events (such as today’s NoPathAction function). Do you have some use cases in mind which would specially require the usage of events?

So I basically have a queue system for my NPCs, something like you’d see in The Sims. I’d like to update that queue when, for example, the Humanoid stops walking, because it would have other actions to do, ones that wouldn’t necessarily involve pathfinding.

In this specific case I would recommend you to not use pathfinding when they get in the queue. They can pathfind to the start of the queue and you can use MoveTo to move the characters in queue. It will perform better than any PathfindingService usage.

However I can see where events could be useful, I might consider adding it to next releases.

1 Like

Do you know if there is any fix to this? , my monster seems to be stuck on these spots, and sometimes has troubles jumping between a obstacle, I am running the path on a loop, and also the “ChangeTarget” function, tried changing the AgentRadius and AgentHeight but the change is very small

local pathfindPosition = Vector3.new()

local path = Pathfinding.new(rake, {
	Target = pathfindPosition;
	MovingTarget = false;
	DebugMode = false;
	RandomMove = false;
	DebugWaypoint = true;
	
	AgentParameters = {
		AgentHeight = 5, -- 3
		AgentRadius = 2, -- 2
		AgentCanJump = true,
		AgentCanClimb = true,
		PathSettings = {
			SupportPartialPath = true;
		};
		Costs = {
			PathfindAvoid = 9999;
			Truss = 1;
		}
	}
	
}) :: any



On corners he has this weird slow movement

but to be fair, the module it’s really good at certain things, really excels at it, Maybe this is just roblox’s pathfinder acting this way

Have you checked the navigation mesh on these stairs? It looks like it might be an empty spot on navigation mesh, but it also might not be.

If it’s not empty this might very well be a bug. The goal is making a pathfinding module as flexible as possible, but I only have a handful of scenarios to test with on the initial release, so there might be bugs. I can take a look at it myself if you can provide me the files you used for this.

1 Like

I’ve sent you the place i was testing it on, check your messages

Version v0.2.1

  • Added event support (OnPathBlocked, OnWaypointReached, OnPathCompleted)
  • All t’s can now call the internal DebugPrint with t:DebugPrint(...)

I know I wasn’t sure with adding events at first, but when I used the module on my own game I’m working on I noticed the need, so these three are added and more of them might arrive later on if there’s a need for that.

cc. @n0081337

I will check your issue in detail and let you know about the issues when I have the time.

1 Like