I’m working on a pathfinding script, and it’s been working for the most part, apart from a specific location in my game’s map, the construction site. I’ve done some basic print debugging, and I’ve found that the script is getting stuck in a loop, because if the path is not successful, the script will re-run the function. Through printing, I’ve also found that the path status is Enum.PathStatus.NoPath for a very strange reason. I tried looking on the developer hub for more information as to what causes this and what it means, but learnt nothing about it. Here’s the code
local myHuman = script.Parent:WaitForChild("Humanoid")
local myRoot = script.Parent:WaitForChild("HumanoidRootPart")
local head = script.Parent:WaitForChild("Head")
local lowerTorso = script.Parent:WaitForChild("LowerTorso")
local grab = script.Parent:WaitForChild("Grab")
local grabAnim = myHuman:LoadAnimation(grab)
grabAnim.Priority = Enum.AnimationPriority.Action
local area = script.Parent:WaitForChild("Zone").Value
local lastHealth = myHuman.Health
local lastAttack = tick()
local attackTime = 0.9
local attackDamage = 5
local angry = false
local function yieldTillDamaged()
if myHuman.Health < lastHealth and angry == false then
lastHealth = myHuman.Health
local newCoroutine = coroutine.create(function()
angry = true
wait(25)
angry = false
end)
coroutine.resume(newCoroutine)
end
end
myHuman.HealthChanged:Connect(yieldTillDamaged)
local grabSound = head:WaitForChild("Attack")
function walkRandomly()
local xRand = math.random(-40, 40)
local zRand = math.random(-40, 40)
local goal = area.Position + Vector3.new(xRand,0,zRand)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(myRoot.Position, goal)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
myHuman.Jump = true
end
print("Moving to waypoint!")
myHuman:MoveTo(waypoint.Position)
local timeOut = myHuman.MoveToFinished:Wait(3)
if not timeOut then
myHuman.Jump = true
walkRandomly()
end
end
else
wait(1)
print("Path was not a success, restarting process")
walkRandomly()
end
end
function findPath(target)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(myRoot.Position,target.Position)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success and angry == true then
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
myHuman.Jump = true
end
myHuman:MoveTo(waypoint.Position)
local timeOut = myHuman.MoveToFinished:Wait(3)
if not timeOut then
myHuman.Jump = true
findPath(target)
break
end
if checkSight(target) then
repeat
myHuman:MoveTo(target.Position)
attack(target)
wait(0.1)
if target == nil then
break
elseif target.Parent == nil then
break
end
until checkSight(target) == false or myHuman.Health < 1 or target.Parent.Humanoid.Health < 1
break
end
if (myRoot.Position - waypoints[1].Position).magnitude > 20 then
findPath(target)
break
end
end
end
end
function checkSight(target)
local ray = Ray.new(myRoot.Position, (target.Position - myRoot.Position).Unit * 40)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
if hit then
if hit:IsDescendantOf(target.Parent) and math.abs(hit.Position.Y - myRoot.Position.Y) < 3 then
return true
end
end
return false
end
function findTarget()
local dist = 100
local target = nil
local potentialTargets = {}
local seeTargets = {}
for i, v in ipairs(workspace:GetChildren()) do
local inMissionBool = v:FindFirstChild("IsInMission")
local missionZoneValue = v:FindFirstChild("MissionZone")
local canContinue = false
if inMissionBool and missionZoneValue then
if inMissionBool.Value == true and missionZoneValue.Value == script.Parent.Zone.Value then
canContinue = true
end
end
if canContinue == true then
local human = v:FindFirstChild("Humanoid")
local torso = v:FindFirstChild("HumanoidRootPart")
if human and torso and v.Name ~= script.Parent.Name then
if (myRoot.Position - torso.Position).magnitude < dist and human.Health > 0 then
table.insert(potentialTargets,torso)
end
end
end
end
if #potentialTargets > 0 then
for i,v in ipairs(potentialTargets) do
if checkSight(v) then
table.insert(seeTargets, v)
elseif #seeTargets == 0 and (myRoot.Position - v.Position).magnitude < dist then
target = v
dist = (myRoot.Position - v.Position).magnitude
end
end
end
if #seeTargets > 0 then
dist = 200
for i,v in ipairs(seeTargets) do
if (myRoot.Position - v.Position).magnitude < dist then
target = v
dist = (myRoot.Position - v.Position).magnitude
end
end
end
return target
end
function attack(target)
if (myRoot.Position - target.Position).magnitude < 5 and tick() > lastAttack + attackTime then
lastAttack = tick()
grabAnim:Play()
grabSound:Play()
if target.Parent ~= nil then
target.Parent.Humanoid:TakeDamage(attackDamage)
end
end
end
function died()
wait(5)
game:GetService("Debris"):AddItem(script.Parent,0.1)
end
myHuman.Died:Connect(died)
function main()
local target = findTarget()
print("In main!")
if target then
myHuman.WalkSpeed = 13
print("Target found!")
findPath(target)
else
print("Target not found, walking randomly")
myHuman.WalkSpeed = 8
walkRandomly()
end
end
while wait(0.1) do
if myHuman.Health <= 0 then
break
end
main()
end
Keep in mind, this only fails with characters inside of the construction site in my game, but works everywhere else, despite all of them having the same scripts (I use commands to make sure they do).
If you could tell me why the path is behaving like this, I’d appreciate that. Here’s a video of the NPCs normally:
At the construction site, they stay completely still.