Help with npc Ai

So I’m trying to make an AI that detects closest players and chase after them. I followed a tutorial by GnomeCode, but inside his tutorial, the part where the npc chases the player after they’ve been found uses the normal Humanoid:MoveTo() function, so I decided to try use pathfinding for it but nothing seems to work. Is there anything I can do?

you havent shown any code [limit]

1 Like

This open source module is what you are looking for.

1 Like

my bad. Here you go!

local npc = script.Parent
local myHumanoid = npc:WaitForChild("Humanoid")
local myRoot = npc:WaitForChild("HumanoidRootPart")
local screamSound = npc.Head:WaitForChild("Scream")
npc.PrimaryPart:SetNetworkOwner(nil)

local PathfindingService = game:GetService("PathfindingService")

local function findPlayers()
	local Players = game:GetService("Players"):GetPlayers()
	local maxDistance = 45
	local currentTarget = nil
	
	for i, plr in pairs(Players) do 
		local char = plr.Character
		if char then
			local checkDistance = (myRoot.Position - char.HumanoidRootPart.Position or char.Torso.Position).Magnitude
			
			if checkDistance < maxDistance then
				currentTarget = char
				maxDistance = checkDistance
			else
				currentTarget = nil
				maxDistance = 45
			end
		end
	end
	
	return currentTarget
end

local function attackTarget(specifiedTarget)
	local checkDistance = (myRoot.Position - specifiedTarget.HumanoidRootPart.Position or specifiedTarget.Torso.Position).Magnitude
	
	if checkDistance <= 2 then
		specifiedTarget.Humanoid.Health = 0
	else
		myHumanoid:MoveTo(specifiedTarget.HumanoidRootPart.Position or specifiedTarget.Torso.Position)
	end
end

local function walkRandom()
	local xrandPos = math.random(-50,50)
	local zrandPos = math.random(-50,50)
	local destination = myRoot.Position + Vector3.new(xrandPos,0,zrandPos)
	
	local path = PathfindingService:CreatePath()
	path:ComputeAsync(myRoot.Position, destination)
	for _, waypoint in pairs(path:GetWaypoints()) do 
		local foundTarget = findPlayers()
		if foundTarget and foundTarget.Humanoid.Health > 0 then
			myHumanoid.WalkSpeed = 15
			attackTarget(foundTarget)
		else
			myHumanoid.WalkSpeed = 6
			myHumanoid:MoveTo(waypoint.Position)
			local myHumanoidWait = myHumanoid.MoveToFinished:Wait(1)
			if not myHumanoidWait then
				walkRandom()
				break
			end
		end
	end
end

while true do
	walkRandom()
end
else
				currentTarget = nil
				maxDistance = 45

Remove this else block here,
if a player is found, it’ll set the currentTarget and maxDistance, but what if the next player it loops through is far away? It’ll set that data to nil.

As for your issue, what exactly isn’t working? Have you tried printing out how many waypoints there are? if the script stops anywhere? Use print statements to debug specifically whats going wrong

My issue is that the attack function doesn’t use pathfinding. So the npc would just get stuck on a wall if the targeted player is behind it. I’ve tried some methods but just leads to more problems.

I believe I have found your issue,
local foundTarget = findPlayers()
if foundTarget and foundTarget.Humanoid.Health > 0 then
If a target is found,

you run the attackTarget function, which then only utilises myHumanoid:MoveTo(specifiedTarget.HumanoidRootPart.Position or specifiedTarget.Torso.Position)
which is not pathfinding at all.

You are only using pathfinding for random idle-walking

So should I set up a pathfinding function separately for the attacking and the random walking?

I wouldn’t really suggest random walking as imagine the randomX puts it behind a wall, then it’s gonna do a ‘random walk’ around a big long wall. I’d say just generate a random vector to move by and then use regular :MoveTo, but definitely use pathfinding for attacking (walking to the target)

1 Like

I’ll think about that. Thank you for helping me! :smiley:

no problem, good luck! :slight_smile:
[limit]

1 Like

I think another problem I found is that when the player kept moving when the AI already computed a path, the Ai would finish walking to the old destination, and then compute another path to another destination. Is there any way I could fix that?

Just use the pathfinding module I linked in a while loop. It automatically handles a lot of edge cases during pathfinding and has great functionally. It will save you a giant headache.

1 Like