I made a npc that follows the nearest player by using pathfinding and it works well but sometimes it gets stuck some corners (sometimes it could get rid of these stucks but sometimes it coudlnt) and fails some jumps while it is really easy to jump and pass. so basically i guess i need to make my npc smarter and recompute the path when it gets stuck? here’s the code and a video
local pfs = game:GetService("PathfindingService")
local npc = script.Parent
local humanoid = npc.Humanoid
local root = npc.HumanoidRootPart
local head = npc.Head
local pathparams = {
AgentRadius = 2,
AgentHeight = 5,
AgentCanJump = true,
AgentCanClimb = true,
}
function walkrandom()
local xrandom = math.random(-10,10)
local zrandom = math.random(-10,10)
local goal = root.Position + Vector3.new(xrandom, 0, zrandom)
local path = pfs:CreatePath(pathparams)
path:ComputeAsync(root.Position - Vector3.new(root.Size.Y/0.75, 0), goal)
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid.Jump = true
end
humanoid:MoveTo(waypoint.Position)
local timeout = humanoid.MoveToFinished:Wait()
if not timeout then
print("got stuck")
humanoid.Jump = true
walkrandom()
end
end
else
print("path failed")
wait(0.6)
walkrandom()
end
end
function pathfind(target)
local path = pfs:CreatePath(pathparams)
path:ComputeAsync(root.Position, target.Position)
if path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
--[[for _, waypoint in ipairs(waypoints) do
local pointpart = Instance.new("Part", workspace)
pointpart.Shape = Enum.PartType.Ball
pointpart.Size = Vector3.new(1,1,1)
pointpart.Material = Enum.Material.Neon
pointpart.Color = Color3.fromRGB(255, 255, 255)
pointpart.Anchored = true
pointpart.CanCollide = false
pointpart.Position = waypoint.Position
pointpart.Name = "pointpart"
pointpart.Touched:Connect(function(hitpart)
if hitpart:IsDescendantOf(root.Parent) then
pointpart:Destroy()
end
end)
end]]
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid.Jump = true
end
humanoid:MoveTo(waypoint.Position)
local timeout = humanoid.MoveToFinished:Wait()
if not timeout then
print("got stuck")
humanoid.Jump = true
walkrandom()
break
end
if checksight(target) then
repeat --sadsadsadsadkhjghcfghgvjbklıhugf
print("moving to the target")
humanoid:MoveTo(target.Position)
wait(0.01)
if target == nil then
break
elseif
target.Parent == nil then
break
end
until checksight(target) == false or humanoid.Health < 1 or target.Parent.Humanoid.Health < 1
break
end
if (root.Position - waypoints[1].Position).Magnitude > 20 then
print("target has moved, generating new path")
pathfind(target)
break
end
end
end
end
function checksight(target)
local rcparams = RaycastParams.new()
rcparams.IgnoreWater = false
rcparams.FilterDescendantsInstances = {script.Parent}
local filtertype = Enum.RaycastFilterType.Exclude
local ray = game.Workspace:Raycast(root.Position, (target.Position - root.Position).Unit * 40, rcparams)
if ray then
local hitpart = ray.Instance
if hitpart then
if hitpart:IsDescendantOf(target.Parent) and math.abs(hitpart.Position.Y - root.Position.Y) < 3 then
print("can see the target")
return true
end
end
end
return false
end
function findtarget()
local distance = 150
local target = nil
local potential_targets = {}
local seetargets = {}
for i, v in ipairs(workspace:GetChildren()) do
local humanoidtarget = v:FindFirstChild("Humanoid")
local torsotarget = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
if humanoidtarget and torsotarget and v.Name ~= script.Parent.Name then
if (root.Position - torsotarget.Position).Magnitude < distance and humanoidtarget.Health > 0 then
table.insert(potential_targets, torsotarget)
end
end
end
if #potential_targets > 0 then
for i, v in ipairs(potential_targets) do
if checksight(v) then
table.insert(seetargets, v)
elseif #seetargets == 0 and (root.Position - v.Position).Magnitude < distance then
target = v
distance = (root.Position - v.Position).Magnitude
end
end
end
if #seetargets > 0 then
distance = 150
for i, v in ipairs(seetargets) do
if (root.Position - v.Position).Magnitude < distance then
target = v
distance = (root.Position - v.Position).Magnitude
end
end
end
return target
end
function main()
local targettt = findtarget()
if targettt then
humanoid.WalkSpeed = 16
pathfind(targettt)
else
humanoid.WalkSpeed = 10
walkrandom()
end
end
while wait(0.01) do
if humanoid.Health < 1 then
break
end
main()
end
Sorry for video quality, it was so long i had to compress