How to make NPC follow 1 NPC at a time

I want the NPC to only follow 1 humanoid until it is dead.

local function findTarget()
	local nearesttarget = nil
	local maxDistance = 300

	for i,v in ipairs(workspace:GetDescendants()) do
		if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then
			local human = v:FindFirstChildWhichIsA("Humanoid")
			local wanted = v:FindFirstChild("Wanted")

			if wanted and wanted.Value == true then
				local distance = (character.PrimaryPart.Position - v.PrimaryPart.Position).Magnitude

				if distance <= maxDistance and human.Health > 0 then
					nearesttarget = v
					maxDistance = distance
				end
				
				if human.Health <= 0 then
					currentPath = nil
					foundNextWaypoint = false
					nearesttarget = nil
				end
			end
		end
	end
	if nearesttarget == nil then
		return nil
	else
		if nearesttarget.PrimaryPart ~= nil then
			return nearesttarget.PrimaryPart
		else
			if nearesttarget:FindFirstChild("HumanoidRootPart") then
				return nearesttarget:FindFirstChild("HumanoidRootPart")
			end
		end
	end
end

task.spawn(function()
	while task.wait() do
		findTarget()
		if humanoid.Health <= 0 then
			break
		end
	end
end)
1 Like

Could you perhaps show footage of how to NPC acts when 2 humanoids are present or what the exact problem is?

Your while function might be the problem.

Try using something like this:

spawn(function()
    -- Keep looping until the humanoid's health is less than or equal to 0
    while true do
        -- Call the findTarget function
        findTarget()

        -- Check if the humanoid's health is less than or equal to 0
        if humanoid.Health <= 0 then
            -- Break out of the loop if the humanoid is dead
            break
        end

        -- Wait for the next frame
        task.wait()
    end
end)

Disclaimer: This code was AI generated from: https://chat.openai.com/chat

1 Like

Though, I just noticed that you might not want to be calling findTarget() all the time. That might be causing the NPC to create a new target when you don’t want.

1 Like

The NPC would not know which NPC to go for when chasing NPC’s.

2 Likes

You should definately call the findTarget() function. I was just saying that if you call it from inside the loop that might be the reason why the NPC keeps changing targets. I wasn’t trying to imply getting rid of that function completely.

1 Like

I tried using CurrentTarget

local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")
local WalkSpeed = humanoid.WalkSpeed

local DestinationsFolder = workspace:WaitForChild("Destinations")

local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local foundNextWaypoint = false

local currentPath = nil
local currentTarget = nil
local oldDestination = nil

local function randomWaypoint()
	local waypoint = DestinationsFolder:GetChildren()
	local random = waypoint[math.random(1, #waypoint)]
	return random
end

local function findTarget()
	local nearesttarget = nil
	local maxDistance = 300

	for i,v in ipairs(workspace:GetDescendants()) do
		if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then
			local human = v:FindFirstChildWhichIsA("Humanoid")
			local wanted = v:FindFirstChild("Wanted")

			if wanted and wanted.Value == true then
				local distance = (character.PrimaryPart.Position - v.PrimaryPart.Position).Magnitude

				if distance <= maxDistance and human.Health > 0 then
					nearesttarget = v
					maxDistance = distance
				end
				
				if human.Health <= 0 then
					currentPath = nil
					foundNextWaypoint = false
					nearesttarget = nil
					currentTarget = nil
				end
			end
		end
	end
	if nearesttarget == nil then
		return nil
	else
		if nearesttarget.PrimaryPart ~= nil then
			return nearesttarget.PrimaryPart
		else
			if nearesttarget:FindFirstChild("HumanoidRootPart") then
				return nearesttarget:FindFirstChild("HumanoidRootPart")
			end
		end
	end
end

local function WalkTo(destination)
	local pathParams = {
		AgentHeight = character:GetExtentsSize().Y,
		AgentRadius = 2,
		AgentCanJump = true,
		AgentCanClimb = true,
		WaypointSpacing = 15,
		Costs = {
			Danger = math.huge,
			Climb = 2,
		}
	}

	local path = PathfindingService:CreatePath(pathParams)

	local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, destination.Position)
	end)

	waypoints = {}

	blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
		if blockedWaypointIndex >= nextWaypointIndex then
			blockedConnection:Disconnect()
			WalkTo(destination)
		end
	end)

	if success and path.Status == Enum.PathStatus.Success then
		waypoints = path:GetWaypoints()

		if not reachedConnection then
			reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
				if reached and nextWaypointIndex < #waypoints then
					nextWaypointIndex += 1
					humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
					foundNextWaypoint = true
				else
					if findTarget() and findTarget() ~= nil and currentTarget == nil then
						WalkTo(randomWaypoint())
						currentPath = nil
						foundNextWaypoint = false

					elseif findTarget() and findTarget() ~= nil and currentTarget ~= nil then
						WalkTo(destination)
						currentPath = nil
						foundNextWaypoint = false
					end
				end
			end)
		end

		if waypoints[nextWaypointIndex] and waypoints[nextWaypointIndex].Action == Enum.PathWaypointAction.Jump then
			humanoid.Jump = true
		end

		if foundNextWaypoint == false then
			nextWaypointIndex = 2
			humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
		else
			nextWaypointIndex = 2
		end

	elseif not success and path.Status ~= Enum.PathStatus.Success then
		humanoid:MoveTo(destination.Position)
	end
end

local function walkRandom()
	local random = randomWaypoint()

	if oldDestination ~= random then
		WalkTo(random)
		currentPath = random
		oldDestination = random
	end
end

spawn(function()
	while true do
		if findTarget() and findTarget() ~= nil and currentTarget == nil then
			WalkTo(findTarget())
			currentPath = findTarget()
			currentTarget = findTarget()
			
		elseif findTarget() and findTarget() ~= nil and currentTarget ~= nil then
			WalkTo(currentTarget)
			currentPath = currentTarget
		end

		if currentPath == nil then
			walkRandom()
		else
			WalkTo(currentPath)
		end

		if findTarget() and findTarget() ~= nil then
			humanoid.WalkSpeed = 20
		elseif findTarget() == nil then
			humanoid.WalkSpeed = WalkSpeed
		end
		
		if humanoid.Health <= 0 then
			break
		end
		
		task.wait()
	end
end)
1 Like

The same problem still.


The NPC would still try to chase the dead NPC.

2 Likes

You can use Humanoid:StateChanged to check if the Humanoid’s state has changed to the “Dead” state which is when the humanoid has died.

Read more about Humanoid states here:

1 Like

Didn’t work.

if human.Health <= 0 or human:GetState() == Enum.HumanoidStateType.Dead then
1 Like

Try printing the Humanoid’s health and their State as well to see what the script outputs.

1 Like

there is an event called Humanoid.Died:Connect(Function)
obviously you must refer to the humanoid in order to execute the event

1 Like

also when you execute the event you should anchor the parts of the dead NPC and then remove the Humanoid so it will not chase you anymore

1 Like

the Humanoid:StateChanged is obsolete I do not recommend using it because it would have errors when receiving a little damage

1 Like

Thanks for telling me, there are certainly much better ways to detect when the humanoid’s state has changed.

2 Likes

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