You can do other things, like print the distance from the AI to the nearest player. If it prints nil or something unexpected then you know you have to look at how you find the closest player, or maybe your distance calculation.
If it prints a distance and doesn’t move then you’ve traced it to a pathfinding issue.
Also, if you use Pathfinding and the travel distance time is over 8 seconds then the NPC will stop.
Instead of asking a very vague “how the heck can I do this?” tell me how you’ve tried the steps I’ve suggested and what happened. If you don’t know about any of the steps then ask about that exact part of it.
Try making just 1 zombie spawn and see if that one works properly. If it does and you add a 2nd zombie it breaks then you know the script isn’t referencing which zombie to send to which location.
I can see that you’re using other people’s scripts to do this, and don’t really understand what is going on. I’m not a pro scripter, I’m just trying to help you to be able to figure out where to look to find the source of the issue.
You’re already getting the distance in the findClosestPlayer function, so print("distance = ", distance) to see what it is.
The Character Pathfinding links I posted above tells you EXACTLY how to get an NPC to walk from one point to another. If you’d read it through you would know a little bit about Pathfinding. I see that one person clicked the second link, but nobody has clicked the first link.
You’re getting the position of the closest player in your script, so you can make a path from the zombie to the player’s position.
There are also plenty of posts on the forum about making NPCs move to or follow players. You could try using the Search tool up top to try looking for them.
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local path = PathfindingService:CreatePath({
AgentRadius = 2,
AgentHeight = 6,
AgentCanJump = true,
AgentCanClimb = true,
Costs = {
Climb = 4
}
})
local TEST_DESTINATION = nil
local function findClosestPlayer()
--pcall(function()
local closestPlayer, closestDistance = nil, math.huge
for _, player in ipairs(Players:GetPlayers()) do
local character = player.Character
if character and character:WaitForChild("Humanoid") then
local distance = (character.HumanoidRootPart.Position - script.Parent.PrimaryPart.Position).Magnitude
if distance < closestDistance then
closestPlayer = player
closestDistance = distance
end
end
end
return closestPlayer
--end)
end
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
-- Compute the path
local success, errorMessage = pcall(function()
path:ComputeAsync(script.Parent.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Get the path waypoints
waypoints = path:GetWaypoints()
-- Detect if path becomes blocked
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stop detecting path blockage until path is re-computed
blockedConnection:Disconnect()
-- Call function to re-compute new path
followPath(destination)
end
end)
-- Detect when movement to next waypoint is complete
if not reachedConnection then
reachedConnection = script.Parent.Humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Increase waypoint index and move to next waypoint
nextWaypointIndex += 1
script.Parent.Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Initially move to second waypoint (first waypoint is path start; skip it)
nextWaypointIndex = 2
script.Parent.Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
warn("Path not computed!", errorMessage)
end
end
local ClosestPlayer = findClosestPlayer()
--followPath(TEST_DESTINATION)
if ClosestPlayer then
while task.wait() do
TEST_DESTINATION = ClosestPlayer.Character.PrimaryPart.Position
followPath(TEST_DESTINATION)
end
end
YOO, I THINK I FINALLY FIXED IT! Here is the new script:
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local NPC = script.Parent
local AttackAnim = NPC.Humanoid:LoadAnimation(NPC.Animations.Attack)
local DamageEvent = game.ReplicatedStorage.Events.DamageEvent
local RaycastHitbox = require(ReplicatedStorage.Modules.RaycastHitboxV4)
local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = true,
AgentCanClimb = true,
Costs = {
Climb = 4
}
})
local M1DB = false
local TEST_DESTINATION = nil
local function findClosestPlayer()
--pcall(function()
local closestPlayer, closestDistance = nil, math.huge
for _, player in ipairs(Players:GetPlayers()) do
local character = player.Character
if character and character:WaitForChild("Humanoid") then
local distance = (character.HumanoidRootPart.Position - NPC.PrimaryPart.Position).Magnitude
if distance < closestDistance then
closestPlayer = player
closestDistance = distance
end
end
end
return closestPlayer
--end)
end
local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local function followPath(destination)
local player = findClosestPlayer()
local character = player.Character
local distance = (character.HumanoidRootPart.Position - NPC.PrimaryPart.Position).Magnitude
-- Compute the path
if distance < 10 then
local NewHitbox = RaycastHitbox.new(NPC)
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Exclude
Params.FilterDescendantsInstances = {NPC}
NewHitbox.RaycastParams = Params
AttackAnim:Play()
NewHitbox.Visualizer = true
NewHitbox.OnHit:Connect(function(hit, hum)
if M1DB == false then
if player:FindFirstChild("Invincible").Value == false then
M1DB = true
player:FindFirstChild("Invincible").Value = true
ReplicatedStorage.Events.DamageEvent:FireClient(player)
end
end
end)
NewHitbox:HitStart(1)
task.wait(2)
M1DB = false
end
local success, errorMessage = pcall(function()
path:ComputeAsync(NPC.PrimaryPart.Position, destination)
end)
if success and path.Status == Enum.PathStatus.Success then
-- Get the path waypoints
waypoints = path:GetWaypoints()
-- Detect if path becomes blocked
blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex >= nextWaypointIndex then
-- Stop detecting path blockage until path is re-computed
blockedConnection:Disconnect()
-- Call function to re-compute new path
followPath(destination)
end
end)
-- Detect when movement to next waypoint is complete
if not reachedConnection then
reachedConnection = NPC.Humanoid.MoveToFinished:Connect(function(reached)
if reached and nextWaypointIndex < #waypoints then
-- Increase waypoint index and move to next waypoint
nextWaypointIndex += 1
NPC.Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
else
reachedConnection:Disconnect()
blockedConnection:Disconnect()
end
end)
end
-- Initially move to second waypoint (first waypoint is path start; skip it)
nextWaypointIndex = 2
NPC.Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
end
end
DamageEvent.OnServerEvent:Connect(function(Player, Value)
if Value == "Damage" then
Player.Character.Humanoid:TakeDamage(10)
elseif Value == "" or Value == nil then
Player:FindFirstChild("Invincible").Value = false
end
end)
local ClosestPlayer = findClosestPlayer()
--followPath(TEST_DESTINATION)
if ClosestPlayer then
while task.wait() do
TEST_DESTINATION = ClosestPlayer.Character.PrimaryPart.Position
followPath(TEST_DESTINATION)
end
end