 Woah, alot of likes I see, Thanks guys, Feel free to check out my upcoming roblox game.
Woah, alot of likes I see, Thanks guys, Feel free to check out my upcoming roblox game. 
OPEN❗
Welcome to my first ever tutorial on the devforum, I wanted to make a pathfinding tutorial for such a long time. This may not be the best pathfinding AI tutorial out there. I’m just showing you what i have learned in the past weeks for making a pathfinding AI, without any further ado, let’s begin the tutorial.
note: i suck at explaining scripts :/, also my English kinda sucks as well.
Keep in mind the code under me should be placed in a normal script inside an NPC.
Alright, Lets setup some quick variables
local npc = script.Parent -- the path to the NPC
local human = npc.Humanoid -- getting the humanoid of the npc
local PFS = game:GetService("PathfindingService")
local RUNSERVICE = game:GetService("RunService")
npc.PrimaryPart:SetNetworkOwner(nil)
Well, that was easy, wasn’t it. Lets begin the fun >:), (aka finding the closest target)
–
Let’s create a function with couple of variables in it.
local function findTarget()
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 5000 -- distance
end
Alright. Lets loop through the players and check if theres a character!
local function findTarget()
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 5000 -- distance
	for i,player in pairs(players) do
		if player.Character then
           --codeeeeeeeeeee
		end
	end
	-- return will go here later in the tutorial
end
EPIC
Okay. let’s do the rest!
local function findTarget()
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 5000 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance then
				nearesttarget = target
				maxDistance = distance
			end
		end
	end
	return nearesttarget
end
Alright, so what we are doing is getting the target and distance between the NPC, and the target(in this case its the character)
local target = player.Character
local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
Then checking if the distance, it’s less than the max distance. and setting the nearest target to the target, ANDDD setting the maxDistance to the distance! yay
if distance < maxDistance then
	nearesttarget = target
	maxDistance = distance
end
We almost forgot, lets add one last line of code to the findTarget function
return nearesttarget
All, together the function should look something like this:
local function findTarget()
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 5000 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance then
				nearesttarget = target
				maxDistance = distance
			end
		end
	end
	return nearesttarget
end
PHEWWW, We are done with that. Let’s begin by calculating the path
Start by creating an another function, inside that function there’s just going to be 3 lines of code
local function getPath(destination)
	local path = PFS:CreatePath()
	path:ComputeAsync(npc.HumanoidRootPart.Position, destination)
	return path
end
So what we are doing is creating a path using PathFindingService, and using the ComputeAsync(), to compute a path from a start position to an end position. And returning the path.
Thats over, Hmm, Alright then.
Lets create a 3rd function(wow, loads of functions today aye?), with 2 variables inside. One to get the path function, and the 2nd to get the target function.
local function pathFindTo(destination)
	local path = getPath(destination)
	local target = findTarget()
    --rest of the code
end
Okay, Now lets check if there’s a target and check if the target is not dead.
if target and target.Humanoid.Health > 0 then
		
end
Good. Lets start by creating waypoints. So the AI can walk to them.
for i,waypoint in pairs(path:GetWaypoints()) do
	if waypoint.Action == Enum.PathWaypointAction.Jump then
		human.Jump =true
	end
	human:MoveTo(waypoint.Position)
	human.MoveToFinished:Wait()
end
So currently, we are looping through the waypoints, using the path variable, and using GetWaypoints() to get them. Simple enough right?, and checking if the waypoint action, its a jump action. Then we are going to set the humanoid jump property to true. And the rest is simple.
All together the function should look something like this.
local function pathFindTo(destination)
	local path = getPath(destination)
	local target = findTarget()
	
	if target and target.Humanoid.Health > 0 then
		for i,waypoint in pairs(path:GetWaypoints()) do
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				human.Jump =true
			end
			human:MoveTo(waypoint.Position)
			human.MoveToFinished:Wait()
		end
	end
end
We are almost done!!! Now let’s use RunService
RUNSERVICE.Heartbeat:Connect(function()
	--code
end)
The Heartbeat event fires every frame , after the physics simulation has completed.  
Now lets check if theres a target if so, use the pathFindTo() function, and set the destination as the target.
RUNSERVICE.Heartbeat:Connect(function()
	local target = findTarget()
	
	if target then
		pathFindTo(target:WaitForChild("HumanoidRootPart").Position + (target:WaitForChild("HumanoidRootPart").Velocity.Unit * 7)) -- play around with the number 7 to your liking.
	end
end)
As you can see the script works very well, It still needs some improvements, But you can do that on your own :>
FULL SCRIPT
local npc = script.Parent
local human = npc.Humanoid
local PFS = game:GetService("PathfindingService")
local RUNSERVICE = game:GetService("RunService")
npc.PrimaryPart:SetNetworkOwner(nil)
local function findTarget()
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 5000 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance then
				nearesttarget = target
				maxDistance = distance
			end
		end
	end
	return nearesttarget
end
local function getPath(destination)
	local path = PFS:CreatePath()
	path:ComputeAsync(npc.HumanoidRootPart.Position, destination)
	return path
end
local function pathFindTo(destination)
	local path = getPath(destination)
	local target = findTarget()
	
	if target and target.Humanoid.Health > 0 then
		for i,waypoint in pairs(path:GetWaypoints()) do
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				human.Jump =true
			end
			human:MoveTo(waypoint.Position)
			human.MoveToFinished:Wait()
		end
	end
end
RUNSERVICE.Heartbeat:Connect(function()
	local target = findTarget()
	
	if target then
		pathFindTo(target:WaitForChild("HumanoidRootPart").Position + (target:WaitForChild("HumanoidRootPart").Velocity.Unit * 7))
	end
end)
Q: Why does the AI twitch in the video?
A: Because, We are generating the path infront of the player by 7 studs. As i just said in the script, Play around with the number.
(target:WaitForChild("HumanoidRootPart").Velocity.Unit * 7)







