In most Roblox games, enemies independently chase you and bunch up, colliding into each other and attacking all at once. While this can be sufficient in a zombie game, a more advanced combat game would get chaotic and overwhelming. In many popular games outside of Roblox melee NPCs tend to wait for fellow melee NPCs to finish their attack before striking. They walk up to different points around the player, instead of all heading directly for the player and ending up bunched up over other NPCs.
While I have some ideas as to how I can make a less chaotic system such that enemies consider each other and spread out and attack at different moments, it seems like a common enough mechanic that its worth checking if any of you know any guides to achieving this or have implemented this yourself/have tips to achieve this.
You can store all the NPC inside a folder in the workspace, then handle all the same NPC which have the same attacks and cooldowns using a temporary while loop including for i, Npc in pairs (Folder:GetChildren())do
There is an example i juste made for you, of course there is simple and better optimized way to do it using tables and modules but yeah it is just an example ^^:
--//Variables//--
local WorkspaceService = game:GetService("Workspace")
local FolderNPC = WorkspaceService:WaitForChild("NPC" ,300)
local NormalZombieEnabled = false
local StrongZombieEnabled = false
--//Functions//--
local function NormalZombie()
NormalZombieEnabled = true
while NormalZombieEnabled == true do
task.wait()
for _,Child in pairs(FolderNPC:GetChildren())do
if Child:IsA("Model")and Child.Name == "NormalZombie" then
--Detection / Move / Attack / cooldown
end
end
end
end
local function StrongZombie()
StrongZombieEnabled = true
while StrongZombieEnabled == true do
task.wait()
for _,Child in pairs(FolderNPC:GetChildren())do
if Child:IsA("Model")and Child.Name == "StrongZombie" then
--Detection / Move / Attack / cooldown
end
end
end
end
local function Activation(NPC)
if NPC.Name == "NormalZombie" and NormalZombieEnabled == false then
coroutine.resume(coroutine.create(function()
NormalZombie()
end))
elseif NPC.Name == "StrongZombie" and StrongZombieEnabled == false then
coroutine.resume(coroutine.create(function()
StrongZombie()
end))
end
end
local function Desactivation(NPC)
local Remaining = false
for _,Child in pairs(FolderNPC:GetChildren())do
if Child:IsA("Model")and Child.Name == NPC then
Remaining = true
end
end
if Remaining == false and NPC.Name == "NormalZombie" then
NormalZombieEnabled = false
elseif Remaining == false and NPC.Name == "StrongZombie" then
StrongZombieEnabled = false
end
end
--//Connections//--
FolderNPC.ChildAdded:Connect(function(NPC)
if NPC:IsA("Model") and NPC:FindFirstChild("Humanoid")then
Activation(NPC)
end
end)
FolderNPC.ChildRemoved:Connect(function(NPC)
Desactivation(NPC)
end)