What could I do to optimize this zombie script?

You have to go thru some hassle, yes, but it will definitely give better results

That is not true, you can just use one while true loop that runs 10 times a second and loops though all entities and send their position data to the client

1 Like

It could be that the Heartbeat function is the one causing the lag. If you don’t show us the code, how do you expect us to help you?

Who would want to steal code that runs at 13 FPS? They could just use zombies from the Toolbox, like the official one, or the developer-made ones. Realistically, your code are not trade secrets. Anybody could write the exact same code as you if they had the same thought process on how they should work.

1 Like

Here is the code


Basically I spawn in a zombie using a function and I then scan for the nearest player from the zombies position and whoever it is I using pathfinding service in a post simulation/heart beat function to move the zombie to the waypoint that is closer to the player then the previous one. And yes I tried slower loops e.g while true do task.wait() end while true do nothing inside even end It seems to be the only thing that works. It is also getting late now so I hope with all of this information somebody might help find the solution quicker. I am also quite new to pathfindingservice so I don’t know all the optimization tips and nooks and crannies.

I am less concerned about people stealing the code, more so about people messing with it making it not function.

They can’t edit your code from their computer? If people take your code, add it to their own project, then break it, it’s not your problem.


  • Why are you using task.spawn in the RunService function? I think this could be a significant contributor. There is no point in doing it, as events work in a way that you can imagine as having a built-in task.spawn
  • You should not be computing pathfinding so often. It can be very slow. You can have it compute only every once in a while like so:
-- how long it has been since we last updated our path to our target
local TimeSincePathUpdate = math.huge
-- which waypoint of the path we are following
local WaypointIdx = 1

-- what to do when we reach a waypoint
Humanoid.MoveToFinished:Connect(function(Reached)
    if Reached then
        -- we got to a waypoint, move on to the next
        WaypointIdx += 1
    else
        -- force path to recompute since we could not reach the waypoint
        -- humanoids automatically give up and fire MoveToFinished
        -- after 8 seconds.
        -- math.huge is just a really big number
        TimeSincePathUpdate = math.huge
    end
end)

RunService.PostSimulation:Connect(function(Delta)
    -- update how long it has been since we updated our path
    -- "delta" is the time between frames
    TimeSincePathUpdate  += Delta
    
    -- recompute our path every half a second
    if TimeSincePathUpdate > 0.5 then
        -- do stuff to recompute path, i.e. :FindPathAsync
        -- since we just updated the path, set this to 0
        TimeSincePathUpdate = 0
        -- reset our waypoint progress
        WaypointIdx = 1
    end
    
    local CurrentWaypoint = Path:GetWaypoints()[WaypointIdx]
    
    if CurrentWaypoint then
        Humanoid:MoveTo(CurrentWaypoint.Position)
    else
        -- we have reached the end of the path, recompute another
        TimeSincePathUpdate = math.huge
    end
end)
  • You can do the same thing with findNearestTarget, where you only update targets every once in a while. With many players in the server, it can slow down a lot
  • findNearestTarget does not need to scan the entirety of the Workspace for players. You could just do something like this:
local function findNearestTarget(hrp)
    local nearestTarget = nil
    local closestDistance = math.huge
    
    -- go through every player
    -- much faster than going through the ENTIRE workspace, where
    -- 99.999% of objects are not player characters.
    for _, Player in game:GetService("Players"):GetChildren() do
        if Player.Character then
            -- check distance, check if it is the closest one, etc
        end
    end
    
    return nearestTarget
end
  • I also spotted a bug:
if Distance < closestDistance then
    nearestTarget = v
    closestDistance = Distance
else
    -- don't do this!
    -- if there are more than two players, the zombie has a chance of
    -- freezing in place FOREVER
    -- if, for example, the script checks PlayerA, and then PlayerB
    -- and PlayerB is further from the zombie, 
    -- the zombie will forget about PlayerA, and just freeze in place!
    nearestTarget = nil
    closestDistance = math.huge
end

That was all I noticed. But look at that! By showing all of the code that matters, I have optimized it and even pointed out a bug. It would just be faster if you put all of the relevant code in the main post. But, I hope this helps!

I was saying that the exploiters could edit the code while playing a round and make the zombies not be able to reach them and also what happens in the

    nearestTarget = v
    closestDistance = Distance
else
    -- doesn't the target become nil if the player dies or is out of range then it's nobody?

    nearestTarget = nil
    closestDistance = math.huge
end

Also I need that task.spawn() so all the zombies can move and target somebody at the same time, without it they all lag.

They cannot edit server code? Sending it won’t help them to edit it.

No, it’s just a distance check? It’s not even checking the player’s health.

If there are two players, then one is guaranteed to be further from the zombie while still being in it’s attack range, and being checked after a player closer to the zombie, Distance will be greater than closestDistance, triggering this check to set the target to nil, effectively making the zombie “forget” about the good target it had.