I’m pretty new to the pathfinding service, but I have a general grasp of how it works. I have a (somewhat) working AI that follows you which utilizes the service, walking around obstacles to get to the target. However, the movement is very buggy once you start to move.
I’m using for loops to sift through waypoints and have the NPC move to that point. When the target moves, the path is recomputed and the new waypoints are reset (and in this process, the waypoint loop breaks to prevent previous waypoints affecting it).
Alongside this, I am using while loops to change the target or recompute the path if need be.
I know this isn’t very effective, which is what brings me here today. How should I go about scripting a pathfinding AI that follows you?
Example of how my pathfinding script works:
https://gyazo.com/199cd2cab69025a723b16c3043e91b4f
Code (yes, some of the variables aren’t used, I’ve had to redo some of the code a bit and forgot to remove them):
--// SERVICES \\--
local PathfindingService = game:GetService('PathfindingService')
local RunService = game:GetService('RunService')
--// CONSTANTS \\--
local HumanoidCharacter = script.Parent
local Humanoid = HumanoidCharacter:FindFirstChildOfClass('Humanoid')
local MaxRange = 200
local RecomputeFrequency = 1
local Recomputing = false
local AutoRecompute = true
local LastPath = 0
local PathCoordinates = {}
local CurrentNodeIndex = 1
local Path = PathfindingService:CreatePath()
local FrequencyTarget
local TargetHumanoid
local LastTargetPosition
local ResettingPath = false
local IsMoving = false
local Waypoints = {}
local NPC = {}
function NPC:ComputePath()
if not Recomputing then
Recomputing = true
Path:ComputeAsync(HumanoidCharacter.HumanoidRootPart.Position, TargetHumanoid.HumanoidRootPart.Position)
Waypoints = Path:GetWaypoints()
Recomputing = false
ResettingPath = false
end
end
function NPC:FollowPath()
IsMoving = true
local Distance
for _, Waypoint in pairs(Waypoints) do
if not ResettingPath then
Humanoid:MoveTo(Waypoint.Position)
repeat
Distance = (Waypoint.Position - HumanoidCharacter.HumanoidRootPart.Position).Magnitude
wait()
until Distance <= 5
else
IsMoving = false
break
end
end
end
function NPC:FindNewTarget()
for _, Character in pairs(workspace:GetChildren()) do
if Character:IsA('Model') and game:GetService('Players'):GetPlayerFromCharacter(Character) then
if TargetHumanoid then
if (Character.HumanoidRootPart.CFrame.p - HumanoidCharacter.HumanoidRootPart.CFrame.p).Magnitude <= MaxRange then
if (Character.HumanoidRootPart.CFrame.p - HumanoidCharacter.HumanoidRootPart.CFrame.p).Magnitude <= (TargetHumanoid.HumanoidRootPart.CFrame.p - HumanoidCharacter.HumanoidRootPart.CFrame.p).Magnitude then
TargetHumanoid = Character
LastTargetPosition = TargetHumanoid.HumanoidRootPart.Position
end
end
else
if (Character.HumanoidRootPart.CFrame.p - HumanoidCharacter.HumanoidRootPart.CFrame.p).Magnitude <= MaxRange then
TargetHumanoid = Character
LastTargetPosition = TargetHumanoid.HumanoidRootPart.Position
end
end
end
end
end
while RunService.Heartbeat:Wait() do
if TargetHumanoid and (TargetHumanoid.HumanoidRootPart.CFrame.p - HumanoidCharacter.HumanoidRootPart.CFrame.p).Magnitude > MaxRange then
TargetHumanoid = nil
LastTargetPosition = nil
FrequencyTarget = nil
end
if not TargetHumanoid or FrequencyTarget ~= TargetHumanoid then
NPC:FindNewTarget()
end
if TargetHumanoid and LastTargetPosition ~= TargetHumanoid.HumanoidRootPart.Position then
ResettingPath = true
NPC:ComputePath()
NPC:FollowPath()
end
if not IsMoving and TargetHumanoid then
ResettingPath = true
NPC:ComputePath()
NPC:FollowPath()
end
if TargetHumanoid then
LastTargetPosition = TargetHumanoid.HumanoidRootPart.Position
FrequencyTarget = TargetHumanoid
end
end