See if the script is running at all by putting a single print statement at the top of the script like: print("Hello World!")
The script is running. It did print the statement.
Put a print statement at the beginning of every function to see which ones are calling. Also, determine which functions should be calling at what time, in what order, so you can walk through the script’s logical steps and see what’s going wrong. Whenever there are no errors but something isn’t running, there’s usually some code you need to add or a piece of logic that needs to be changed.
I’m actually working on a fairly complex system myself. I might have to check this video out.
Except mine uses Object Oriented Programming to assign every Zombie it’s own controller and set of unique stats shared under a single concept.
It allows a ton more flexibility. For instance, I can replace one, or even a group, of zombies behavior with a new behavior. Like if a Queen Zombie walks past a Zombie it will cause the Zombie to stay near her and follow her.
And causing this unique behavior is as simple as replacing the AiOrder of the Zombie with a different AiOrder.
Whenever you’re doing something like you are currently doing, it’s highly recommended to use OOP concepts.
Anyways, did you set up your tags correctly? Like, did you give zombies the “Zombie” tag?
so your Initalize code is this
function initialize()
for i, zomtag in pairs(collectionservice:GetTagged("Zombie")) do
You Probably want to switch collectionservice:GetTagged("Zombie")
to a zombie folder.
You should also make sure you have at least one model tagged as a Zombie.
I use Tag Editor By Sweetheartichoke to view and edit tags
Notice how if there are no tagged items it wont execute the code:
for k,v in pairs(game:GetService("CollectionService"):GetTagged("unusedtag")) do
print("test")
end
print("Fin")
Output:
10:45:43.243 Fin
Ok, so I created a function in my script that tags the zombies.
function tagzomb(obj)
if obj.Name == "Zombie" then
collectionservice:AddTag(obj, "Zombie")
end
print("tagged "..obj.Name)
end
It prints that it tags the zombie, but I am not sure what to do next.
You can call the function outside of the loop and then the zombies should be tagged.
Ok so I have now…
Here is my current script. It still does not work, but there are more print statements printing.
local collectionservice = game:GetService("CollectionService")
local zombies = {}
function spawner(func,...)
local co = coroutine.wrap(func)
co(...)
end
function updatetarget()
local humans = collectionservice:GetTagged("Human")
for i, zombie in pairs(zombies) do
local dist = 1000
local target = nil
local zomhumroot = zombie.HumanoidRootPart
for i, human in pairs(humans) do
if human:FindFirstChild("Humanoid") and human:FindFirstChild("HumanoidRootPart") then
local humanoid = human:FindFirstChild("Humanoid")
local humroot = human:FindFirstChild("HumanoidRootPart")
if humanoid and humroot and human ~= zombie then
if humanoid.Health > 0 then
if (zomhumroot.Position - humroot.Position).magnitude < dist then
dist = (zomhumroot.Position - humroot.Position).magnitude
target = humroot
end
end
end
end
end
zombie.target = target
print("targeted")
return target
end
end
spawner(function()
while wait(1) do
updatetarget()
print("Updating target")
end
end)
function walktotarget(zombie)
local humroot = updatetarget()
print("k")
if humroot then
print("Found humroot")
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(humroot.Position, humroot)
zombie.walkanim:Play()
end)
print("Walking")
else
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(zombie.humroot.Position + Vector3.new(math.random(-50,50),0, math.random(-50,50)), game.Workspace.Part)
zombie.walkanim:Stop()
zombie.idleanim:Play()
wait(3)
zombie.idleanim:Stop()
zombie.walkanim:Play()
end)
print("Random walking")
end
end
function movementhandler(zombie)
print("Movement")
while wait(1) do
if zombie.humanoid.Health <= 0 then
print("noooooooo")
break
end
print("no")
if zombie.target then
walktotarget(zombie)
print("Movement controleld")
end
end
end
function attack(zombie)
local human = zombie.target.Parent.Huamnoid
human:TakeDamage(15)
zombie.attackanim:Play()
end
spawner(function()
while wait(0.5) do
for i, zombie in pairs(zombies) do
local human = updatetarget()
if zombie.target then
if (zombie.HumanoidRootPart.Position - human.Position).magnitude < 5 then
attack(zombie)
print("attacked")
end
end
end
end
end)
function taghuman(instance)
local human = instance:FindFirstChild("Humanoid")
if human then
collectionservice:AddTag(human, "Human")
end
end
function tagzomb(instance)
if instance.Name == "Zombie" then
local zombie = instance.Zombie
if zombie then
collectionservice:AddTag(zombie, "Zombie")
end
print("done")
end
end
function removezomb(zombie)
local index = table.find(zombies, zombie)
table.remove(zombies, index)
wait(2)
zombie.char:Destroy()
end
function addzomb(zomanoid)
table.insert(zombies, {
char = zomanoid.Parent,
humroot = zomanoid.Parent.HumanoidRootPart,
humanoid = zomanoid,
target = nil,
attackanim = zomanoid:LoadAnimation(zomanoid.Attack),
walkanim = zomanoid:LoadAnimation(zomanoid.Walk),
idleanim = zomanoid:LoadAnimation(zomanoid.Idle)
})
for i, zombie in pairs(zombies) do
if zombie.humanoid == zomanoid then
zombie.humanoid.Died:Connect(function() removezomb(zombie) end)
for i, part in pairs(zombie.char:GetDescendants()) do
if part:IsA("BasePart") and part:CanSetNetworkOwnership() then
part:SetNetworkOwner(nil)
end
end
spawner(movementhandler, zombie)
print("walking")
break
end
end
end
game.Workspace.ChildAdded:Connect(taghuman)
game.Workspace.ChildAdded:Connect(tagzomb)
collectionservice:GetInstanceAddedSignal("Zombie"):Connect(function(zomanoid)
addzomb(zomanoid)
end)
function initialize()
for i, tag in pairs(collectionservice:GetTagged("Zombie")) do
local found = false
for i, zomb in pairs(zombies) do
if zomb.humanoid == tag then
found = true
end
end
if not found then
addzomb(tag)
end
end
for i, human in pairs(game.Workspace:GetChildren()) do
taghuman(human)
end
end
initialize()
I recognise the format of this code to be similar to this:
https://www.roblox.com/library/4694469710/Multi-NPC-Control
I don’t know if kangerujack is the true originator of this code, but it certainly works and is a good base to build from.
Howevre, the code expects all NPCs to be present at the startup of the script (as does yours) and doesn’t cater for incremental loading of them.
Do you have all your NPCs in the workspace at startup? If not, you need to have a game loop to Clone an NPC from storage, then use CollectionService to tag it with a “Zombie” tag. Your script above, will then see the newly tagged NPC and start controlling it.
I see. I do have a spawner script inside of a zombie spawner I made and added the little code to tag the zombies humanoid. It tags the zombies, but the zombies still do not move.
Spawner script:
local collectionservice = game:GetService("CollectionService")
for i, spawner in pairs(script.Parent:GetChildren()) do
if spawner.Name == "Spawner" then
while true do
local zombieclone = game.ReplicatedStorage.Zombie:Clone()
zombieclone.UpperTorso.CFrame = spawner.CFrame
zombieclone.Parent = game.Workspace
collectionservice:AddTag(zombieclone.Zombie, "Zombie")
wait(3)
end
end
end
Controller script now:
local collectionservice = game:GetService("CollectionService")
local zombies = {}
function spawner(func,...)
local co = coroutine.wrap(func)
co(...)
end
function updatetarget()
local humans = collectionservice:GetTagged("Human")
for i, zombie in pairs(zombies) do
local dist = 1000
local target = nil
local zomhumroot = zombie.HumanoidRootPart
for i, human in pairs(humans) do
if human:FindFirstChild("Humanoid") and human:FindFirstChild("HumanoidRootPart") then
local humanoid = human:FindFirstChild("Humanoid")
local humroot = human:FindFirstChild("HumanoidRootPart")
if humanoid and humroot and human ~= zombie then
if humanoid.Health > 0 then
if (zomhumroot.Position - humroot.Position).magnitude < dist then
dist = (zomhumroot.Position - humroot.Position).magnitude
target = humroot
end
end
end
end
end
zombie.target = target
print("targeted")
return target
end
end
spawner(function()
while wait(1) do
updatetarget()
print("Updating target")
end
end)
function walktotarget(zombie)
local humroot = updatetarget()
print("k")
if humroot then
print("Found humroot")
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(humroot.Position, humroot)
zombie.walkanim:Play()
end)
print("Walking")
else
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(zombie.humroot.Position + Vector3.new(math.random(-50,50),0, math.random(-50,50)), game.Workspace.Part)
zombie.walkanim:Stop()
zombie.idleanim:Play()
wait(3)
zombie.idleanim:Stop()
zombie.walkanim:Play()
end)
print("Random walking")
end
end
function movementhandler(zombie)
print("Movement")
while wait(1) do
if zombie.humanoid.Health <= 0 then
print("noooooooo")
break
end
print("no")
if zombie.target then
walktotarget(zombie)
print("Movement controleld")
end
end
end
function attack(zombie)
local human = zombie.target.Parent.Huamnoid
human:TakeDamage(15)
zombie.attackanim:Play()
end
spawner(function()
while wait(0.5) do
for i, zombie in pairs(zombies) do
local human = updatetarget()
if zombie.target then
if (zombie.HumanoidRootPart.Position - human.Position).magnitude < 5 then
attack(zombie)
print("attacked")
end
end
end
end
end)
function taghuman(instance)
local human = instance:FindFirstChild("Humanoid")
if human then
collectionservice:AddTag(human, "Human")
end
end
function removezomb(zombie)
local index = table.find(zombies, zombie)
table.remove(zombies, index)
wait(2)
zombie.char:Destroy()
end
function addzomb(zomanoid)
table.insert(zombies, {
char = zomanoid.Parent,
humroot = zomanoid.Parent.HumanoidRootPart,
humanoid = zomanoid,
target = nil,
attackanim = zomanoid:LoadAnimation(zomanoid.Attack),
walkanim = zomanoid:LoadAnimation(zomanoid.Walk),
idleanim = zomanoid:LoadAnimation(zomanoid.Idle)
})
for i, zombie in pairs(zombies) do
if zombie.humanoid == zomanoid then
zombie.humanoid.Died:Connect(function() removezomb(zombie) end)
for i, part in pairs(zombie.char:GetDescendants()) do
if part:IsA("BasePart") and part:CanSetNetworkOwnership() then
part:SetNetworkOwner(nil)
end
end
spawner(movementhandler, zombie)
print("walking")
break
end
end
end
game.Workspace.ChildAdded:Connect(taghuman)
collectionservice:GetInstanceAddedSignal("Zombie"):Connect(function(zomanoid)
addzomb(zomanoid)
end)
function initialize()
for i, tag in pairs(collectionservice:GetTagged("Zombie")) do
local found = false
for i, zomb in pairs(zombies) do
if zomb.humanoid == tag then
found = true
end
end
if not found then
addzomb(tag)
end
end
for i, human in pairs(game.Workspace:GetChildren()) do
taghuman(human)
end
end
initialize()
print("initialized")
P.S. nothing from the walktotarget function prints. I tried adjusting my code more to the script inside of the multiple ai controller model.
The main NPC control script expects the “zombie” tag to be in the Humanoid itself. Change you tagging to this:
-- TAG NPC
local human = zombieClone:FindFirstChildWhichIsA("Humanoid")
if human then
collectionservice:AddTag(human,"NPC")
end
You do have a Humanoid in your NPCs don’t you?
Yes I do have humanoids in my npcs.
So like this?
Script:
local collectionservice = game:GetService("CollectionService")
for i, spawner in pairs(script.Parent:GetChildren()) do
if spawner.Name == "Spawner" then
while true do
local zombieclone = game.ReplicatedStorage.Zombie:Clone()
zombieclone.UpperTorso.CFrame = spawner.CFrame
zombieclone.Parent = game.Workspace
local humanoid = zombieclone:FindFirstChildWhichIsA("Humanoid")
if humanoid then
collectionservice:AddTag(humanoid, "Zombie")
end
wait(3)
end
end
end
Yeah, that should be good. Does it work?
If it doesn’t work, can you confirm that the Zombie clones are being cloned in to the workspace. Do you see the print statement appear from this line?
collectionservice:GetInstanceAddedSignal("Zombie"):Connect(function(zomanoid)
addzomb(zomanoid)
print("Added zomb tag to zomanoid")
end)
Yes it does print!! Thank you!
Now the problem now is the code doesn’t work. I am not sure what is wrong with my code because I implemented it from the single zombie code. I feel like there is something wrong with the walking function though because it does not execute.
local collectionservice = game:GetService("CollectionService")
local zombies = {}
function spawner(func,...)
local co = coroutine.wrap(func)
co(...)
end
function updatetarget()
local humans = collectionservice:GetTagged("Human")
for i, zombie in pairs(zombies) do
local dist = 1000
local target = nil
local zomhumroot = zombie.HumanoidRootPart
for i, human in pairs(humans) do
if human:FindFirstChild("Humanoid") and human:FindFirstChild("HumanoidRootPart") then
local humanoid = human:FindFirstChild("Humanoid")
local humroot = human:FindFirstChild("HumanoidRootPart")
if humanoid and humroot and human ~= zombie then
if humanoid.Health > 0 then
if (zomhumroot.Position - humroot.Position).magnitude < dist then
dist = (zomhumroot.Position - humroot.Position).magnitude
target = humroot
end
end
end
end
end
zombie.target = target
print("targeted")
return target
end
end
spawner(function()
while wait(1) do
updatetarget()
print("Updating target")
end
end)
function walktotarget(zombie)
local humroot = updatetarget()
print("k")
if humroot then
print("Found humroot")
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(humroot.Position, humroot)
zombie.walkanim:Play()
end)
print("Walking")
else
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(zombie.humroot.Position + Vector3.new(math.random(-50,50),0, math.random(-50,50)), game.Workspace.Part)
zombie.walkanim:Stop()
zombie.idleanim:Play()
wait(3)
zombie.idleanim:Stop()
zombie.walkanim:Play()
end)
print("Random walking")
end
end
function movementhandler(zombie)
print("Movement")
while wait(1) do
if zombie.humanoid.Health <= 0 then
print("noooooooo")
break
end
print("no")
if zombie.target then
walktotarget(zombie)
print("Movement controleld")
end
end
end
function attack(zombie)
local human = zombie.target.Parent.Huamnoid
human:TakeDamage(15)
zombie.attackanim:Play()
end
spawner(function()
while wait(0.5) do
for i, zombie in pairs(zombies) do
local human = updatetarget()
if zombie.target then
if (zombie.HumanoidRootPart.Position - human.Position).magnitude < 5 then
attack(zombie)
print("attacked")
end
end
end
end
end)
function taghuman(instance)
local human = instance:FindFirstChild("Humanoid")
if human then
collectionservice:AddTag(human, "Human")
end
end
function removezomb(zombie)
local index = table.find(zombies, zombie)
table.remove(zombies, index)
wait(2)
zombie.char:Destroy()
end
function addzomb(zomanoid)
table.insert(zombies, {
char = zomanoid.Parent,
humroot = zomanoid.Parent.HumanoidRootPart,
humanoid = zomanoid,
target = nil,
attackanim = zomanoid:LoadAnimation(zomanoid.Attack),
walkanim = zomanoid:LoadAnimation(zomanoid.Walk),
idleanim = zomanoid:LoadAnimation(zomanoid.Idle)
})
for i, zombie in pairs(zombies) do
if zombie.humanoid == zomanoid then
zombie.humanoid.Died:Connect(function() removezomb(zombie) end)
for i, part in pairs(zombie.char:GetDescendants()) do
if part:IsA("BasePart") and part:CanSetNetworkOwnership() then
part:SetNetworkOwner(nil)
end
end
spawner(movementhandler, zombie)
print("walking")
break
end
end
end
game.Workspace.ChildAdded:Connect(taghuman)
collectionservice:GetInstanceAddedSignal("Zombie"):Connect(function(zomanoid)
addzomb(zomanoid)
print("Added zomanoid")
end)
function initialize()
for i, tag in pairs(collectionservice:GetTagged("Zombie")) do
local found = false
for i, zomb in pairs(zombies) do
if zomb.humanoid == tag then
found = true
end
end
if not found then
addzomb(tag)
end
end
for i, human in pairs(game.Workspace:GetChildren()) do
taghuman(human)
end
end
initialize()
print("initialized")
It does not print k or found humroot or Walking.
There’s a couple of possible issues in the code but you will need to work through them. We know that CollectionService is seeing the NPC added event and that addzomb() is firing as you see the print statement which comes after it.
Next step is to debug the addzomb(zomanoid)
function. I would add a few print statements in the ```for`` loop as I think this is the place where it is falling over next.
for i, zombie in pairs(zombies) do
print("Zombie added to Table, checking Humanoid")
if zombie.humanoid == zomanoid then
print("Zombie Humanoid found")
zombie.humanoid.Died:Connect(function() removezomb(zombie) end)
for i, part in pairs(zombie.char:GetDescendants()) do
if part:IsA("BasePart") and part:CanSetNetworkOwnership() then
print("Set NetOwnership", part)
part:SetNetworkOwner(nil)
end
end
spawner(movementhandler, zombie)
print("walking")
break
end
end
You can see that each point that the script makes a decision, I add a following print statement. It’s a great way to see if the script is making the decisions you expect and need it to do. I follow exactly the same procedure when debugging my own work when things look chaotic, it’s just an easy way to do it.
See how you get on and report back.
I could give you a working version of the script, but that would not help you to learn, so you can work out these things in the future. Sorry for being a pita.
Every print statement is actually printing. It is probably the movement functions that aren’t working, but I am not sure where I went wrong.
If you paste the current code here then I will have a look later tonight and try and see what is wrong.
Okay thank you. I have been working on different ways I could do this, so it would be nice if you could look over the code. I will provide both the code that I have for a single zombie and the multiple zombie controller script that doesn’t work.
Single Zombie Script:
local zombie = script.Parent
local zomhumroot = zombie.HumanoidRootPart
local zomanoid = zombie.Zombie
-- do not worry about the animations
local anim = zomanoid.Walk
local anim2 = zomanoid.Attack
local anim3 = zomanoid.Idle
local loadanim = zomanoid:LoadAnimation(anim)
local loadanim2 = zomanoid:LoadAnimation(anim2)
local loadanim3 = zomanoid:LoadAnimation(anim3)
function findtarget()
local dist = 1000
local target = nil
for i, human in pairs(game.Workspace:GetChildren()) do
if human:FindFirstChild("Humanoid") and human:FindFirstChild("HumanoidRootPart") then
local humanoid = human:FindFirstChild("Humanoid")
local humroot = human:FindFirstChild("HumanoidRootPart")
if humanoid and humroot and human ~= zombie then
if humanoid.Health > 0 then
if (zomhumroot.Position - humroot.Position).magnitude < dist then
dist = (zomhumroot.Position - humroot.Position).magnitude
target = humroot
end
end
end
end
end
return target
end
while wait(1) do
local humroot = findtarget()
if humroot then
zomanoid:MoveTo(humroot.Position, humroot)
loadanim:Play()
if (zomhumroot.Position - humroot.Position).magnitude < 5 then
loadanim2:Play()
humroot.Parent.Humanoid:TakeDamage(15)
end
else
zomanoid:MoveTo(zomhumroot.Position + Vector3.new(math.random(-50,50),0, math.random(-50,50)), game.Workspace.Part)
loadanim:Stop()
loadanim3:Play()
wait(3)
loadanim3:Stop()
loadanim:Play()
end
end
Multiple zombie controller:
local collectionservice = game:GetService("CollectionService")
local zombies = {}
function spawner(func,...)
local co = coroutine.wrap(func)
co(...)
end
function updatetarget()
local humans = collectionservice:GetTagged("Human")
for i, zombie in pairs(zombies) do
local dist = 1000
local target = nil
local zomhumroot = zombie.HumanoidRootPart
for i, human in pairs(humans) do
if human:FindFirstChild("Humanoid") and human:FindFirstChild("HumanoidRootPart") then
local humanoid = human:FindFirstChild("Humanoid")
local humroot = human:FindFirstChild("HumanoidRootPart")
if humanoid and humroot and human ~= zombie then
if humanoid.Health > 0 then
if (zomhumroot.Position - humroot.Position).magnitude < dist then
dist = (zomhumroot.Position - humroot.Position).magnitude
target = humroot
end
end
end
end
end
zombie.target = target
print("targeted")
return target
end
end
spawner(function()
while wait(1) do
updatetarget()
print("Updating target")
end
end)
function walktotarget(zombie)
local humroot = updatetarget()
print("k")
if humroot then
print("Found humroot")
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(humroot.Position, humroot)
zombie.walkanim:Play()
end)
print("Walking")
else
spawner(function()
wait(0.5)
zombie.humanoid:MoveTo(zombie.humroot.Position + Vector3.new(math.random(-50,50),0, math.random(-50,50)), game.Workspace.Part)
zombie.walkanim:Stop()
zombie.idleanim:Play()
wait(3)
zombie.idleanim:Stop()
zombie.walkanim:Play()
end)
print("Random walking")
end
end
function movementhandler(zombie)
print("Movement")
while wait(1) do
if zombie.humanoid.Health <= 0 then
print("noooooooo")
break
end
print("no")
if zombie.target then
walktotarget(zombie)
print("Movement controleld")
end
end
end
function attack(zombie)
local human = zombie.target.Parent.Huamnoid
human:TakeDamage(15)
zombie.attackanim:Play()
end
spawner(function()
while wait(0.5) do
for i, zombie in pairs(zombies) do
local human = updatetarget()
if zombie.target then
if (zombie.HumanoidRootPart.Position - human.Position).magnitude < 5 then
attack(zombie)
print("attacked")
end
end
end
end
end)
function taghuman(instance)
local human = instance:FindFirstChild("Humanoid")
if human then
collectionservice:AddTag(human, "Human")
end
end
function removezomb(zombie)
local index = table.find(zombies, zombie)
table.remove(zombies, index)
wait(2)
zombie.char:Destroy()
end
function addzomb(zomanoid)
table.insert(zombies, {
char = zomanoid.Parent,
humroot = zomanoid.Parent.HumanoidRootPart,
humanoid = zomanoid,
target = nil,
attackanim = zomanoid:LoadAnimation(zomanoid.Attack),
walkanim = zomanoid:LoadAnimation(zomanoid.Walk),
idleanim = zomanoid:LoadAnimation(zomanoid.Idle)
})
for i, zombie in pairs(zombies) do
print("Zombie added to table")
if zombie.humanoid == zomanoid then
print("Zomanoid found")
zombie.humanoid.Died:Connect(function() removezomb(zombie) end)
for i, part in pairs(zombie.char:GetDescendants()) do
if part:IsA("BasePart") and part:CanSetNetworkOwnership() then
print("Set ownership", part)
part:SetNetworkOwner(nil)
end
end
spawner(movementhandler, zombie)
print("walking")
break
end
end
end
game.Workspace.ChildAdded:Connect(taghuman)
collectionservice:GetInstanceAddedSignal("Zombie"):Connect(function(zomanoid)
addzomb(zomanoid)
print("Added zomanoid")
end)
function initialize()
for i, tag in pairs(collectionservice:GetTagged("Zombie")) do
local found = false
for i, zomb in pairs(zombies) do
if zomb.humanoid == tag then
found = true
end
end
if not found then
addzomb(tag)
end
end
for i, human in pairs(game.Workspace:GetChildren()) do
taghuman(human)
end
end
initialize()
print("initialized")
Thank you for your help so far @BadDad2004 it really helps!
Sorry it took a while as I was busy on other things. Your script as it stands fails to find a valid Player target.
I have reworked it a bit (a lot) as I was testing. Put this updated script into ServerScriptService and copy your Zombie to ServerStorage:
-- SERVICES
local serverstorage = game:GetService("ServerStorage") -- Needed for Zombie Cloning
local CollectionService = game:GetService("CollectionService")
--VARIABLES
local zombieClone = serverstorage.Zombie -- Zombie NPC Clone
local zombieFolder = workspace.NPCs -- Workspace folder for Zombies in game - don't keep everything in Workspace
local zombies = {} -- Table used to keep track of all alive zombies
--Used to create new threads easily while avoid spawn()
function spawner(func,...)
local co = coroutine.wrap(func)
co(...)
end
--------------------------
----Zombie AI Handling----
--------------------------
--Simple function for getting the distance between 2 points
function checkDist(part1,part2)
if typeof(part1) ~= Vector3 then part1 = part1.Position end
if typeof(part2) ~= Vector3 then part2 = part2.Position end
return (part1 - part2).Magnitude
end
--Loops through the human tag to find the closest valid target
function updateTarget()
local humans = CollectionService:GetTagged("Human")
for _,zombie in pairs(zombies) do
local target = nil
local dist = 200
for _,human in pairs(humans) do
local root = human.RootPart
if root and human.Health > 0 and checkDist(root,zombie.root) < dist and human.Parent.Name ~= zombie.char.Name then
dist = checkDist(root,zombie.root)
target = root
end
end
zombie.target = target
end
end
--Target updating
spawner(function()
while wait(1) do
updateTarget()
end
end)
--Called to have the zombie path towards it's current target
function pathToTarget(zombie)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(zombie.root.Position, zombie.target.Position)
local waypoints = path:GetWaypoints()
local currentTarget = zombie.target
for i,v in pairs(waypoints) do
if v.Action == Enum.PathWaypointAction.Jump then
zombie.human.Jump = true
else
zombie.human:MoveTo(v.Position)
spawner(function()
wait(0.5)
if zombie.human.WalkToPoint.Y > zombie.root.Position.Y then
zombie.human.Jump = true
end
end)
zombie.human.MoveToFinished:Wait()
if not zombie.target then
break
elseif checkDist(currentTarget,waypoints[#waypoints]) > 10 or currentTarget ~= zombie.target then
pathToTarget(zombie)
break
end
end
end
end
--Simple loop to handle the pathfinding function
function movementHandler(zombie)
while wait(1) do
if zombie.human.Health <= 0 then
break
end
if zombie.target then
pathToTarget(zombie)
end
end
end
function attack(zombie)
local human = zombie.target.Parent.Humanoid
human:TakeDamage(10)
zombie.grabAnim:Play()
end
spawner(function()
while wait(0.5) do
for _,zombie in pairs(zombies) do
if zombie.target then
if checkDist(zombie.target,zombie.root) < 5 then
attack(zombie)
end
end
end
end
end)
-------------------------------
----Zombie Table Management----
-------------------------------
-- Create new Zombie instance
local function cloneZombie()
local newZombie = zombieClone:Clone()
newZombie.PrimaryPart.Position = Vector3.new(math.random(-100, 100), math.random(-100, 100), math.random(-100, 100))
newZombie.Parent = zombieFolder
tagNewZombie(newZombie)
end
--Simple function to check instances for humanoid then tag them if found
function tagHuman(instance)
local human = instance:FindFirstChildWhichIsA("Humanoid")
if human then
CollectionService:AddTag(human,"Human")
end
end
--Simple function to check instances for humanoid then tag them if found
function tagNewZombie(instance)
local human = instance:FindFirstChildWhichIsA("Humanoid")
if human then
CollectionService:AddTag(human,"Zombie")
end
end
--Respawning that is tied the to the .Died event
function removeZombie(zombie)
-- You could add stuff in here to reward points to the Player with leaderstats
local index = table.find(zombies,zombie)
table.remove(zombies,index)
wait(1)
zombie.char:Destroy()
end
--Adds Zombies to Zombies table, sets up respawning,
--and spawns a pathing thread for each zombie.
function addZombie(zombieHumanoid)
table.insert(zombies,{
char = zombieHumanoid.Parent,
root = zombieHumanoid.RootPart,
human = zombieHumanoid,
target = nil,
clone = zombieHumanoid.Parent:Clone(),
grabAnim = zombieHumanoid:LoadAnimation(zombieHumanoid.Parent.Grab)
})
for _,zombie in pairs(zombies) do
if zombie.human == zombieHumanoid then
zombie.human.Died:Connect(function() removeZombie(zombie) end)
for i,v in pairs(zombie.char:GetDescendants()) do
if v:IsA("BasePart") and v:CanSetNetworkOwnership() then
v:SetNetworkOwner(nil)
end
end
spawner(movementHandler,zombie)
break
end
end
end
--Checking each object in the workspace for a humanoid as it enters/respawns
workspace.ChildAdded:Connect(tagHuman)
--Whenever something is tagged as a zombie then we add it to our table of alive zombies
CollectionService:GetInstanceAddedSignal("Zombie"):Connect(function(zombieHumanoid)
addZombie(zombieHumanoid)
end)
--Ran one time to add all current zombies in the workspace on run
function intialize()
for _,v in pairs(CollectionService:GetTagged("Zombie")) do
local found = false
for _,x in pairs(zombies) do
if x.human == v then
found = true
end
end
if not found then
addZombie(v)
end
end
for i,v in pairs(workspace:GetChildren()) do
tagHuman(v)
end
end
intialize()
-- Have constantly spawning Zombies from Server Storage
-- Just copy your Zombie to ServerStorage
wait(10) -- Let the server settle down as checks & tags the Players
-- ZOMBIE CLONE LOOP - Spawns a new Zombie every 10 seconds from ServerStorage
while true do
cloneZombie()
wait(5)
end
Let us know how you get on.
Thank you @BadDad2004! It started working, so I will mark as solution, but I plan to do it my way instead of yellow mustangs way. The zombies animations are a little buggy, and not too long ago, I thought about using module scripts, so I will be developing a new way to do this. Thank you for your help thus far!!! :DDD