How to make pathfinding NPC smoother

I would like for my NPC to run smoother as right now it moves down pathfinding but keeps stopping when near player(As it is programmed to do) but it just overall looks bad.

I’ve looked at a couple “solutions” on the devforum but they don’t seem to show their problem so I am not sure if our problems are the same and they also have different code set up such as one using raycasting.

This is the code that I am using

local function findTarget2()
	local plrList = Players:GetPlayers()
	local nearestPlayer = nil
	local distance = nil
	local direction = nil
	local char = nil
	for i,v in pairs(plrList) do
		char = v.Character
		if char then
			local distVector = (v.Character.HumanoidRootPart.Position - root.Position)
			if not nearestPlayer then
				nearestPlayer = v
				distance = distVector.magnitude
				direction = distVector.Unit
			elseif distVector.magnitude <= distance then
				nearestPlayer = v
				distance = distVector.magnitude
				direction = distVector.Unit
			end
		end
	end
	return char,direction
end

local function checkDist(distance,torso)
	if distance <= 6 then
		trackHum.WalkSpeed = hum.WalkSpeed
	else 
		trackHum.WalkSpeed = 30
		local path = pathFind:CreatePath()
		path:ComputeAsync(trackTorso.Position,torso.Position)
		local waypoints = path:GetWaypoints()
		for i,v in pairs(waypoints) do
			trackHum:MoveTo(v.Position)
		end
	end
end

while wait(.1) do
	root:SetNetworkOwner(nil)
	local char,direction = findTarget2()
	if char then
		local torso = char.HumanoidRootPart
		local distance = (torso.Position-root.Position).magnitude
		if distance <= targetDistance then
			CombatSystem()
		end
		if distance <= 100 then
			checkDist(distance,torso)
		end

	end
end


If anyone has worked with pathfinding before or npc creation lmk what has helped you. Please and thank you!
!

I recommend creating the path, but playing around with the WaypointSpacing value as described here.

local path = PFS:CreatePath({
	AgentRadius = 2,
	AgentHeight = 5,
	AgentCanJump = true,
	WaypointSpacing = 1
})

This one might make it seem smoother, but you can make it math.huge if you want waypoints only where needed.

4 Likes

How would I implement the spacing I see the variable but do you have to actually do anything else?

Nope, unless you’re unsatisfied with it. You can change the values as needed, but I think that this is meant to replace some chunk of code you’re not giving us, but we don’t need that.

1 Like

Where is your main function that actually moves the AI?

1 Like

You could add a raycast loop inside your movement code/function. If the AI can directly see the player, do a loop that directly uses MoveTo() towards the player’s HumanoidRootPart instead of a calculated waypoint.

This will smoothly move the AI towards the player without any stuttering.

Solution 1

Since your game will most likely be mostly open space, a simple ‘Move straight to target when NPC is close enough’ will work.

Nobody wants to fight in a maze anyways, not even an NPC.


Solution 2

In most games, the melee NPC have melee attacks that work like ranged attacks; they jump / dash towards the player before swinging their sword. This can hide the imperfections of the pathfinding.

Example:

  • Literally all melee machines / humans in Horizon Zero Dawn
  • Aloy’s melee in Horizon Zero Dawn
  • Some enemies in Elden Ring

For your case, an ‘anchor this NPC, play an animation, and tween to target position, then (insert how your game deals damage here)’ will work.


1 Like

I forgot to ask last night but how would I use math.huge?

Such a difficult question to answer, but to put it simply, math.huge is infinity. Certain functions are designed to work with math.huge to create different outcomes, such as what was done with PathfindingService. If you’re asking for a code example, that was also posted above.

always remember to mark an answer as solution if it’s the solution.

2 Likes

Yeh i will remember to do that but im also curious still on what people do.

As described in my first post, there is some code you don’t give us.
You need to replace the CreatePath part with this:

local path = PFS:CreatePath({
	AgentRadius = 2,
	AgentHeight = 5,
	AgentCanJump = true,
	WaypointSpacing = 1
})