AI Pathing script support and improving

  1. What do you want to achieve? Keep it simple and clear!

I’ve been working on an advanced AI pathing script for caves. And I want to perfect it so it follows the player seamlessly.

  1. What is the issue? Include screenshots / videos if possible!

So I have a working script so far, but the AI is a bit delayed on updating to the players current position. I’ll send a video for reference. I’ll also send the script to see anyone can see any faults.

I’ve used a lot of resources from the Developer Hup already but I am still quite new to coding.

Code is here:

local Players = game:GetService("Players")
local Pathfinding = game:GetService("PathfindingService")
local RunSerivce = game:GetService("RunService")
local Entity = script.Parent
local rig = Entity.Humanoid:FindFirstChild("Animator")
local Root = Entity:FindFirstChild("HumanoidRootPart")
local alignOrientation = Root:FindFirstChild("AlignOrientation")

-- Pathfinding AI
local Humanoid = Entity:WaitForChild("Humanoid")
Entity.PrimaryPart:SetNetworkOwner(nil)

local recompute = true
local pathUpdate = false

local waypoints
local nextWaypointindx
local reachConnection
local blockedConnection = nil

local Walkspeed = Entity:GetAttribute("Walkspeed")
local SprintSpeed = Entity:GetAttribute("SprintSpeed")
local Damage = Entity:GetAttribute("Damage")
local Stopping = Entity:GetAttribute("Stop")

local function getPath(destination)
	local path = Pathfinding:CreatePath({
		AgentHeight = 4,
		AgentRadius = 5,
		AgentCanClimb = true,
		AgentCanJump = true,
		Costs = {
			Water = math.huge
		}
	})
	path:ComputeAsync(Root.Position, destination.Position)
	return path
end

local function findTarget()
	local  nearestTarget
	local MaxDistance = 100
	for index, player in pairs(Players:GetPlayers()) do
		if player.Character then
			local target = player.Character
			local distance = (Root.Position - target.HumanoidRootPart.Position).Magnitude
			if distance < MaxDistance then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end
	return nearestTarget
end

local Cooldown = 3
local Debounce = false

local function attack()
	local connection
	connection = Entity.Humanoid.Touched:Connect(function(hit)
		if not Debounce and hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Humanoid.Health > 0 then
			Debounce = true
			connection:Disconnect()
			Entity.Humanoid.WalkSpeed = Stopping
			Attack:Play()
			task.wait(0.5)
			hit.Parent.Humanoid:TakeDamage(10)
			print("You've been hit")
			task.spawn(function()
				task.wait(Cooldown)
				Debounce = false
			end)
			Attack:Stop()
			Entity.Humanoid.WalkSpeed = Walkspeed
		end
	end)
end

local function TargetPosition(target)
	local oldposition = target.HumanoidRootPart.Position
	if oldposition == nil then
		recompute = true;
	else
		if (oldposition - target.HumanoidRootPart.Position).Magnitude > 2 then
			recompute = true
			oldposition = target.HumanoidRootPart.Position
		end
	end
end



local function Capture(target)
	local distance = (Root.Position - target.HumanoidRootPart.Position).Magnitude
	
	while true do
		local NewPath = Pathfinding:CreatePath({
			AgentHight = 4,
			AgentRadius = 5,
			AgentCanClimb = true,
			AgentCanJump = true,
			Costs = {
				Water = math.huge
			}
		})
		if pathUpdate then
			return
		end
		pathUpdate = true
		if recompute then
			local success, failure = pcall(function()
				NewPath:ComputeAsync(Root.Position, target.HumanoidRootPart.Position)
			end)
			
			if distance > 5 and target.Humanoid.Health > 0 then
				if success and NewPath.Status == Enum.PathStatus.Success then
					waypoints = NewPath:GetWaypoints()
					if blockedConnection == nil then
						blockedConnection = NewPath.Blocked:Connect(function(blockedindex)
							if recompute then
								blockedConnection:Disconnect()
								blockedConnection = nil
							else
								if blockedindex >= nextWaypointindx then
									recompute = true
									blockedConnection:Disconnect()
									blockedConnection = nil
								end
							end
						end)
					end
					nextWaypointindx = 2
					for index, target in pairs(NewPath:GetWaypoints()) do
						if not Walk.IsPlaying then
							Walk:Play()
						end
						Humanoid:MoveTo(target.Position)
						Humanoid.MoveToFinished:Wait()
					end
				else
					Humanoid:MoveTo(target.Position - (Root.CFrame.LookVector * 10))
				end
			else
				attack()
			end
		end
		pathUpdate = false
		task.wait(0.01)
	end
end

local function walkTo(destination)
	local path = getPath(destination)
	if path.Status == Enum.PathStatus.Success then
		for index, waypoint in pairs(path:GetWaypoints()) do
			local target = findTarget()
			if target and target.Humanoid.Health > 0 then
				TargetPosition(target)
				Capture(target)
				break
			else
				Entity.Humanoid.WalkSpeed = Walkspeed
				Humanoid:MoveTo(waypoint.Position)
				Humanoid.MoveToFinished:Wait()
			end
		end
	else
		Humanoid:MoveTo(destination.Position - (Root.CFrame.LookVector * 10))
	end
end

local function Patrol()
	local waypoints = workspace.Waypoints:GetChildren()
	local ranWaypoint = math.random(1, #waypoints)
	walkTo(waypoints[ranWaypoint])
end

attack()

while true do
	Patrol()
	task.wait(0.01)
end

Example gif here
Pathfinding_002