Pathfinding A.I problem

Well I was revisiting my old games and found this pathfinding code I made myself with the help of ChatGPT when I was a noobie… I suddenly got the passion to continue the project, and I’m wondering if the code is well optimized and how to fix this bug with the fricking bot:
(I’m the blue one, the bot is the red one)

The path is INDEED possible:

(I don’t know what’s the white square on the right)

Well, here’s the code, and, if you can help, thanks!

local pathfindingService = game:GetService("PathfindingService")
local HumanoidZ = script.Parent.Humanoid

local function TorsoLocal(Position)
	local List = workspace:GetChildren()
	local Torso = nil
	local Distancia = script.Distance.Value
	local NPC1 = nil
	local NPC2 = nil
	local NPC3 = nil
	local Humanoid = nil
	local PartPrimary = script.Parent.PrimaryPart
	if PartPrimary.Anchored == true then
		PartPrimary.Anchored = false
		
	end
	script.Parent.PrimaryPart:SetNetworkOwner(nil)
	for i = 1, #List do
		NPC2 = List[i]
		if NPC2:IsA("Model") and (NPC2 ~= script.Parent) then
			NPC1 = NPC2:FindFirstChild("Torso")
			NPC3 = NPC2:FindFirstChild("UpperTorso")
			Humanoid = NPC2:FindFirstChild("Humanoid")
			if (NPC1 ~= nil) then
				if (Humanoid ~= nil) and (Humanoid.Health > 0) then
					if (NPC1.Position - script.Parent.HumanoidRootPart.Position).magnitude < Distancia then
						if workspace.EnJuego.Sobrevivientes:FindFirstChild(NPC2.Name) then
							Torso = NPC1
							Distancia = (NPC1.Position - script.Parent.HumanoidRootPart.Position).magnitude
						end
					end
				end
			elseif (NPC3 ~= nil) then
				if (Humanoid ~= nil) and (Humanoid.Health > 0) then
					if (NPC3.Position - script.Parent.HumanoidRootPart.Position).magnitude < Distancia then
						if workspace.EnJuego.Sobrevivientes:FindFirstChild(NPC2.Name) or workspace.EnJuego.Traidores:FindFirstChild(NPC2.Name) then
							Torso = NPC3
							Distancia = (NPC3.Position - script.Parent.HumanoidRootPart.Position).magnitude
						end
					end
				end
			end
		end
	end
	return Torso
end

local recalculateInterval = 0.5  -- Recalculate the path every 0.5 seconds
local lastRecalculateTime = tick()
local currentWaypointIdx = 1
local stuckCheckInterval = 1  -- Check if NPC is stuck every 1 second
local lastStuckCheckTime = tick()
local maxStuckTime = 3 
local isStuckTime = 0
local previousPosition = script.Parent.Torso.Position

local function shouldRecalculatePath()
	local timeSinceLastRecalculate = tick() - lastRecalculateTime
	return timeSinceLastRecalculate >= recalculateInterval
end

local function isStuck()

	local currentPosition = script.Parent.Torso.Position
	local timeSinceLastStuckCheck = tick() - lastStuckCheckTime

	if timeSinceLastStuckCheck >= stuckCheckInterval then
		lastStuckCheckTime = tick()

		-- Check if the NPC has moved
		if (currentPosition - previousPosition).Magnitude < 3 then
			-- Increment the stuck time
			isStuckTime = isStuckTime + timeSinceLastStuckCheck

			-- Check if the NPC has been stuck for too long
			if isStuckTime >= maxStuckTime then
				print("Stuck")
				HumanoidZ.Jump = true
				return true
			end
		else
			-- Reset the stuck time if the NPC has moved
			isStuckTime = 0
		end

		previousPosition = currentPosition
	end

	return false
end

while task.wait() do
	local Central = TorsoLocal(script.Parent.Torso.Position)
	if Central ~= nil then
		local agentParams = {
			["AgentHeight"] = 5,
			["AgentCanJump"] = true,
			["AgentRadius"] = 2,
			["AgentCanClimb"] = true,
		}
		local path = pathfindingService:CreatePath(agentParams)
		path:ComputeAsync(script.Parent.Torso.Position, Central.Position)
		local waypoints = path:GetWaypoints()

		local function OnPathBlocked(blockedWaypointIdx)
			if blockedWaypointIdx > currentWaypointIdx then
				path:ComputeAsync(script.Parent.Torso.Position, Central.Position)
				waypoints = path:GetWaypoints()  -- Update waypoints after recalculating path
				currentWaypointIdx = 1  -- Reset currentWaypointIdx
				TorsoLocal()
			end
		end

		path.Blocked:Connect(OnPathBlocked)  -- Connect to the Blocked event before iterating over the waypoints

		if path.Status == Enum.PathStatus.Success then
			local hum = script.Parent.Humanoid

			for i, waypoint in ipairs(waypoints) do
				local oldPosition = TorsoLocal(script.Parent.Torso.Position).Position


				hum:MoveTo(waypoint.Position)
				hum.MoveToFinished:Wait() -- The movement is choppy because of this but using heartbeat in the loop makes the AI worse
				-- Wait for the NPC to reach the current waypoint
				if shouldRecalculatePath() then
					break
				end

				if waypoint.Action == Enum.PathWaypointAction.Jump then
					hum.Jump = true  -- Trigger the jump action
				end

				if isStuck() then
					path:ComputeAsync(script.Parent.Torso.Position, Central.Position)
					waypoints = path:GetWaypoints()  -- Update waypoints after recalculating path
					currentWaypointIdx = i  -- Reset currentWaypointIdx
					HumanoidZ.Jump = true
					break
				end

			end
		else
			print("No valid path found")
		end
		lastRecalculateTime = tick()  -- Update the last recalculate time

	end
end

2 Likes

You dont have to use for loop for waypoints.

2 Likes

Can you elaborate? I’m the antonym of nerd but in real life

Just get the 3rd point of the waypoint instead of looping, it will be faster because you dont need all the waypoints for path unless you want a static path.

if #pathwaypoints >=3 the
humanoid go to (waypoint[3].Position) etc

1 Like

Problem fixed :skull: It was an outside variable

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.