In my game, once there’s too many zombies the framerate starts dropping horrendously and the CPU struggles so I want to find some solutions to this. Aside from the obvious reducing the number of zombies I want to know if this may be an error in my scripting since I see these other tower defense games with hundreds of enemies walking through and still maintaining bearable frames even on mobile.
Zombie Code:
(target is an ObjectValue)
local function Zombie()
while task.wait(1/6) do
-- Zombie Targeting Code
if target.Value ~= nil and target.Value.PrimaryPart ~= nil then
humanoid:MoveTo(target.Value.PrimaryPart.Position)
local ray = castRay()
if ray and ray.Instance and canAttack then
attack(ray)
end
if target.Value.Name and target.Value:FindFirstChild("Humanoid") and target.Value.Humanoid.Health <= 0 then
wait(5.5)
local name = target.Value.Name
target.Value = workspace:FindFirstChild(name)
end
else
zombie:Destroy()
end
end
end
workspace.DescendantAdded:Connect(function(instance)
if instance:HasTag("Zombie") then
task.spawn(Zombie, instance)
end
end)
If the reason for all the lag is the humanoids, should I replace them with something else?
I’ll provide extra details if needed
(p.s i think its probably because im starting a new while wait loop for every zombie but quote me on this)
instead of spawning a new loop for every zombie that spawns, i believe you can use just one loop to handle all zombies via. the use of collectionservice
Turn off CanQuery And CanTouch properties on parts that don’t need it and also don’t use Humanoids they’re way too unoptimized and one last thing, don’t use instance values, use attributes instead.
I would not use wait() functions here at all, but instead have a table of zombies and their data like targets, states and timers that would be reset every x miliseconds (using RunService for timer updates) triggering state/target changes.
hmm that could work but the reason why i use while task.wait(1/6) is because i want the script to only run 6 times a second as opposed to RunService.Heartbeat which runs mostly at 60 times a second
One thing I noticed which is also creating lag but a different kind aka ping lag is your server receive, you are stressing the server way too much, consider moving some stuff to the client with server sanity checks, as well as check for memory leaks you probably have a few
You can disable humanoid states to gain a little bit of performance, also you can disable collisions on parts and replace them with hitbox like stuff, for gameplay, you should create enemy-limiter, it’s psychological trick
See, most of the time players will have enough power to turn 100 enemies into dust quick, instead of doing more and more each wave, scale enemies to like 50 or soo and increase their size and HP
If using physic to move some npc recommend maximun 100 NPC. Never do loop per zombie just enough use 1 loop control everything also make sure turn CollisionGroup each zombie. There way using tween but i still not made it
Example NPCs use physic to move - No Pathfinding and no attack
local function spawn_zombie(Name,Position)
local Zombie=game.ServerStorage[Name]:Clone()
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated,false) -- These all mostly state can disabled
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Flying,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.StrafingNoPhysics,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Physics,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp,false)
Zombie.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Running,false)
Zombie.Parent=workspace.npc
Zombie:MoveTo(Position)
Zombie.Humanoid:AddTag('Zombie')
for i,v in pairs(Zombie:GetChildren())do
if v:IsA'BasePart'then
v:SetNetworkOwner(nil)
end
end
end
function search_to_attack(v)
local list=workspace:children() -- i can say it's better to put NPC another folder
local d=200 -- Distance
local temp,human,temp2,torso
for x=1,#list do
temp2=list[x]
if temp2:FindFirstChild'Humanoid'then
temp=temp2:findFirstChild'HumanoidRootPart'
human=temp2:findFirstChild'Humanoid'
if temp~=nil and human.Health>0 then
if(temp.Position-v.Torso.Position).magnitude<d then
torso=temp
d=(temp.Position-v.Torso.Position).magnitude
end end end end return torso end
task.delay(0,function()
while task.wait(.5)do -- Used follow someone and i recommend loop just single
for i,v in pairs(game.CollectionService:GetTagged'Zombie')do
if v then
local target=search_to_attack(v)
if target~=nil then
v:MoveTo(target.Position,target)
end
end
end
end
end)
-- vvv Not important just spawn zombie vvv
local zombiecount=0
task.delay(0,function()
while task.wait(.1)do
zombiecount+=1
print(zombiecount)
spawn_zombie( -- Time to spawn 1 NPC
'Zombie', -- Name of zombie in ServerStorage what ever
Vector3.new(math.random(-50,50),3,math.random(-50,50) -- Spawn Position
))
end
end)
well for one if you have any tables on the server make sure to remove players data from it when they leave another is leaving instances connected, if you can you should always disconnect when OR if u only need it connected once consider using :Once. You can check if you have data leaks by opening lua heap and seeing if it is constantly rising with being GCed, u can also check if the amount of instances in game keep rising. Garbage Collection and Memory Leaks in Roblox - What you should know, also instead of making a loop to keep updating move to consider using the roblox pathfinding or you can use renderstepped instead, but u would want to do that with Collection service, u could also cache all the zombies in a table then see which zombies are in range and only send that moving data to them
Also try to avoid using while loops, try to opt for something else like runservice, and why are u using instances values what are you even storing in them?
my solution its better about use how does humanoidrootpart its anchored then move use cframe way better rather than use physic moving it does use alot cpu
My example bullet tracing render in 1 loop.... script just too mess but not too long