What do you want to achieve? Keep it simple and clear!
I am writing an npc that would walk through checkpoints and also handle blocked paths.
What is the issue? Include screenshots / videos if possible!
The problem is that my NPC won’t avoid the obstacles, he simply walks into them.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I tried to use the :ComputeAsync() function again, so I could recompute the path, but the function can only compute the path once, and I also tried to search up for solutions on this forum but I got nothing I wanted. Help appreciated.
local npc = script.Parent
local hum = npc.Humanoid
local rs = game:GetService("RunService")
local ps = game:GetService("PathfindingService")
local path = ps:CreatePath()
local function getpath(dst)
path:ComputeAsync(npc.HumanoidRootPart.Position, dst.Position)
return path
end
local function walkto(dst)
local path = getpath(dst)
for index, waypoints in pairs(path:GetWaypoints()) do
hum:MoveTo(waypoints.Position)
hum.MoveToFinished:Wait()
end
end
path.Blocked:Connect(function(dst)
walkto(dst)
end)
while true do
walkto(workspace.dst1)
walkto(workspace.dst2)
walkto(workspace.dst3)
walkto(workspace.dst4)
end
When new obstacles appear, you need to create a new navigation mesh with ps:CreatePath in your example. You should be doing that in your getpath function as well.
Creating a new navigation mesh in getpath function was a mistake, because my character does not move at all when I run the script. Or maybe I am doing something wrong?
It’s better sometimes to, instead of re-inventing the wheel, use the assets around you. It makes sense when you want to grow, but it doesn’t hurt to take a look at the documentation, how the module was formed, and what ideas can be put into your head upon looking at somebody else’s method. You can basically ‘study’ their methods, and create your own if you are so adamant, however.
In order to recompute the NPC’s path you would need to also do some additional things like:
local myRoot = script.Parent:WaitForChild("HumanoidRootPart")
local myHuman = script.Parent:WaitForChild("Humanoid")
function getUnstuck()
myHuman:Move(Vector3.new(math.random(-1,1),0,math.random(-1,1)))
wait(0.3)
end
function getDistance(target)
distance = (myRoot.Position - target.Position).Magnitude
return distance
end
function pathToTarget(target)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(myRoot.Position,target.Position)
if path.Status == Enum.PathStatus.Success then
pathFailCount = 0
local waypoints = path:GetWaypoints()
for i,v in ipairs(waypoints) do
if v.Action == Enum.PathWaypointAction.Jump then
myHuman.Jump = true
end
myHuman:MoveTo(v.Position)
local moveSuccess = myHuman.MoveToFinished:Wait()
if not moveSuccess then
break
end
end
else
pathFailCount = pathFailCount + 1
if pathFailCount > 10 then
pathFailCount = 0
getUnstuck()
end
end
end
function main()
local targetDistance = getDistance(target)
if targetDistance < 1 then
getUnstuck()
else
pathToTarget(target)
end
end
while wait(0.1) do
main()
end
Thanks man! I edited the script to make the NPC walk around the checkpoints endlessly and now it works as intended! But there is one small issue: when the path gets blocked, the NPC hits the blocking object, waits for a few seconds and then walks the recomputed path, I dont want him to wait, how would I fix that? (I would mark your post as a solution if you at least give me a hint)
Maybe try to make an obstacle detection function. Try to make something like this: (Note: it will only work if the objects are called “Part”
-- etc
function FindObstacle()
local distance = 40
local obstacle = nil
for i,v in pairs(game.workspace:GetChildren()) do
local part = v:FindFirstChild("Part")
if (myRoot.Position - part.Position).magnitude < distance then
distance = (myRoot.Position - part.Position).magnitude
end
end
return obstacle
end
function escapeObstacle(obstacle)
myHumanoid:MoveTo(-(Vector3.new((30),0,(30))) * (obstacle.Position))
while (myRoot.Position - obstacle.Position).magnitude > distance do
break
end
end
function main()
local targetDistance = getDistance(target)
local object = findObstaclet()
if object then
escapeObstacle(object)
else if targetDistance < 1 then
getUnstuck()
else
pathToTarget(target)
end
end
while wait(0.1) do
main()
end
Well yeah, this is not operational code, just an example. Even with this one though, you can’t really achieve what you want easily. You would need to do pretty complex things to continually detect objects and recompute paths without waiting.