Pathfinding Find Closest Player

I am currently making a Backrooms game, and I’m working on an entity called the “Hound”, and it chases the player unless they keep eye contact with it. But besides the point, I’m currently working on a system where they chase the closest player, but I am having some trouble with it. I’m not sure how I can find the closest player and then move the entity to that player, here is a script I’ve tried but doesn’t work at all.

--Services--
local RunService = game:GetService('RunService')
local PathfindingService = game:GetService('PathfindingService')

--Variable--
local hum = script.Parent.Humanoid
local humrp = script.Parent.HumanoidRootPart
local Animator = hum.Animator

--Pathfinding
local playerDistances = {}
local destination = workspace.Part.Position

local path = PathfindingService:CreatePath()
path:ComputeAsync(humrp.Position, destination)

local waypoints = path:GetWaypoints()

local function findPlayerDistances()
	local RefreshDistances = coroutine.wrap(function()
		while wait() do
			for i,v in pairs(game.Players:GetPlayers()) do
				local char = v.Character or v.CharacterAdded:Wait()

				table.insert(playerDistances,{(char.HumanoidRootPart.Position - humrp.Position).Magnitude, char.HumanoidRootPart.Position})
			end
			
			table.clear(playerDistances)
		end
	end)
	RefreshDistances()
end

findPlayerDistances()
2 Likes
local pathfindingService = game:GetService("PathfindingService")
local tweenService = game:GetService("TweenService")
local character = script.Parent
local humanoid = character:WaitForChild("Monster")
local chase_magnitude = character.Configuration.NoticeDistance.Value
local run_speed = character.Configuration.RunSpeed.Value
local walk_speed = character.Configuration.WalkSpeed.Value

local chasing = false
local dead = false
local originalC1 = character.Head.Neck.C1
local http = game:GetService('HttpService')


for index, part in pairs(character:GetDescendants()) do
	if part:IsA("BasePart") then
		part:SetNetworkOwner(nil)
	end
end


function getNearestTarget()
	local nearest_magnitude = math.huge
	local nearest_character = nil
	for index, player in pairs(game.Players:GetPlayers()) do
		if player.Character then
			if player.Character.Humanoid.Health > 0 then
				if (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude <= character.Configuration.NoticeDistance.Value then
					if nearest_magnitude >= (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude then
						nearest_magnitude = (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude
						nearest_character = player.Character
					end
				end
			end
		end
	end
	return nearest_character
end

function getNearestTargetToSniff()
	local nearest_magnitude = math.huge
	local nearest_character = nil
	for index, player in pairs(game.Players:GetPlayers()) do
		if player.Character then
			if player.Character.Humanoid.Health > 0 then
				--if (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude <= character.Configuration.NoticeDistance.Value then
					if nearest_magnitude >= (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude then
						nearest_magnitude = (player.Character.HumanoidRootPart.Position - character.HumanoidRootPart.Position).magnitude
						nearest_character = player.Character
					end
				--end
			end
		end
	end
	return nearest_character
end






function getTouchingParts(part)
	local connection = part.Touched:connect(function() end)
	local results = part:GetTouchingParts()
	connection:Disconnect()
	
	return results
end


while true do
	game:GetService("RunService").Heartbeat:wait()
	local target = getNearestTarget()
		if target then
			character.Chasing.Value = true
			if not chasing then
				chasing = true
			else
					humanoid.WalkSpeed = character.Configuration.RunSpeed.Value
			end
			local origin, direction = character.HumanoidRootPart.Position, (target.HumanoidRootPart.Position - character.HumanoidRootPart.Position).unit * 500
			local ray = Ray.new(origin, direction)
			local hit = workspace:FindPartOnRay(ray, character)
			local pathFind = false
			
			
			if hit then
				if not hit:IsDescendantOf(target) then
					pathFind = true
				end
			end
			
			if pathFind then
				if character:FindFirstChild("HumanoidRootPart") then
				local path = pathfindingService:CreatePath()
				path:ComputeAsync(character.HumanoidRootPart.Position, target.HumanoidRootPart.Position)
				local waypoints = path:GetWaypoints()
				for index, waypoint in pairs(waypoints) do
					if waypoint.Action == Enum.PathWaypointAction.Jump then
						humanoid.Jump = true
					end
					
					local origin, direction = character.HumanoidRootPart.Position, (target.HumanoidRootPart.Position - character.HumanoidRootPart.Position).unit * 500
					local ray = Ray.new(origin, direction)
					local hit = workspace:FindPartOnRay(ray, character)
					local pathFind = false
					if hit then
						if not hit:IsDescendantOf(target) then
							pathFind = true
						end
					end
					if not pathFind then
						break
					end
					humanoid:MoveTo(waypoint.Position)
					humanoid.MoveToFinished:wait()
					end
				end
			else
				humanoid:MoveTo(target.HumanoidRootPart.Position)
				if (character.HumanoidRootPart.Position - target.HumanoidRootPart.Position).magnitude <= 7 then
					task.wait(.1)
					
						wait(0.25)
						
						humanoid.WalkSpeed = character.Configuration.RunSpeed.Value
					
					end
				end
		else
			character.Chasing.Value = false
			local chance = math.random(1, 3)
			
			humanoid.WalkSpeed = character.Configuration.WalkSpeed.Value
			chasing = false
			local seconds = 0
			if chance == 1 then
				if getNearestTargetToSniff() then
					humanoid:MoveTo(getNearestTargetToSniff().HumanoidRootPart.Position)
					seconds = 2
				end
			else
				humanoid:MoveTo(Vector3.new(math.random(-330, -67), 0, math.random(-326, 339)))
				seconds = math.random(3, 4)
			end
			for i = seconds/(1/60),1,-1 do
				game:GetService('RunService').Heartbeat:wait()
				if getNearestTarget() then
					break
			end
		end
	end
end

1 Like

I have gotten it working, here is the new script for any people in the future that need it!

--Services--
local RunService = game:GetService('RunService')
local PathfindingService = game:GetService('PathfindingService')

--Variable--
local hum = script.Parent.Humanoid
local humrp = script.Parent.HumanoidRootPart
local Animator = hum.Animator

--Pathfinding
script.Parent.PrimaryPart:SetNetworkOwner(nil)
local destination = workspace.Part.Position

local function findTarget()
	local players = game.Players:GetPlayers()
	local MaxDistance = 200
	local nearestTarget
	
	for i,v in pairs(players) do
		if (v.Character) then
			local target = v.Character
			local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude
			
			if (distance < MaxDistance) then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end
	
	return nearestTarget
end

local function agro(target)
	local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude
	
	if (distance > 8) then
		hum:MoveTo(target.HumanoidRootPart.Position)
	else
		
		target.Humanoid.Health = 0
	end
end

local function createPath(destination)
	local path = PathfindingService:CreatePath()
	path:ComputeAsync(humrp.Position, destination)
	
	return path
end

local function walkTo(destination)
	local path = createPath(destination)
	
	local waypoints = path:GetWaypoints()

	for i,v in pairs(waypoints) do
		local target = findTarget()
		
		if (target) then
			agro(target)
			break
		end
		
		hum:MoveTo(v.Position)

		hum.MoveToFinished:Wait()
	end
end

while task.wait(0.5) do
	walkTo(destination)
end
18 Likes

Hello! I know I am a bit late to this, but I was wondering what the purpose of local destination = workspace.Part.Position? I would like to understand this script more and know if I matters how I use the workspace part. Also my pathfinding character just walks into walls, anyway I could make him walk around (isn’t that the purpose of pathfinding?)

1 Like