Game genres

How to make a zombie survival game in Roblox Studio

A zombie survival game is about pressure that keeps rising until the team breaks. Each wave is a little bigger, a little faster and a little tougher, and the players' job is to spend scarce ammo, cash and health well enough to last one more. This guide covers what makes the genre work, the systems you need, a build plan for a wave survival game (the open-world version builds on it), a server script that spawns escalating waves, and how to monetize a co-op game where nobody loses to someone else's purchase.

Updated 26 October 202610 min readGenre guide

In short

A zombie survival game is a wave spawner that sends more and tougher zombies each round, zombie AI cheap enough to run dozens at once, weapons with limited ammo, barricades to defend and repair, and cash per kill to spend between waves. Build one small map with one weapon, barricades and ten waves first, test it with three friends, then add a weapon shop, perks, revives and more maps.

  • Escalate on several numbers at once (count, health, speed, new zombie types) so later waves feel different, not just longer.
  • Keep the server cost of each zombie low: one simple chase loop, server-owned, and a cap on how many are alive.
  • Scarcity is the fun. If ammo and cash are plentiful, the game is a shooting gallery.
On this page
  1. What makes it work
  2. Systems
  3. Running a horde
  4. Build plan
  5. Wave script
  6. Revives
  7. Monetization
  8. Retention
  9. With RoCode
  10. Questions
  11. Sources

What makes a zombie survival game work

The loop in one line: survive the wave, earn cash, spend it on guns, doors and repairs, survive a bigger wave. Roblox's Survival genre covers games where the objective is to survive, escape or defeat something threatening the players, and a zombie game with lots of shooting may also fit Shooter with the PvE Shooter subgenre. Pick by your core gameplay.

  • Every 10 seconds: triage. Shoot the zombie closest to the window, reload now or after this one, run to the teammate who is down.
  • Every wave: a breather, then a squeeze. The short break between waves is when players shop, repair and plan. The wave is when the plan is tested.
  • Every 5 waves: something new. A fast zombie, a tank, an exploder, a boss wave. New threats force new tactics where bigger numbers alone do not.
  • Every session: a record. The highest wave reached is the score. "We got to wave 23" is the story players tell.
  • Teamwork. Revives, shared doors that one player pays to open, and holding different windows make co-op the natural way to play.

Zombie games that get abandoned usually escalate only health (so late waves are long and boring), let players camp one corner forever, or hand out so much ammo that there is no decision. Good ones make the map itself part of the challenge: you start in a small room and pay to open doors into more space, more weapons and more danger.

Two shapes of the genre exist. Wave survival (this guide's first playable) is round based: defend a place, survive waves. Open-world survival adds scavenging, crafting, hunger and a base that saves; Roblox lists it as the Open World & Survival RPG subgenre. Start with waves: every system it needs, you will need in the open-world version too.

The systems a zombie survival game needs

Systems, the Roblox pieces they use, and where to learn each one
SystemWhat it doesRoblox piecesGuide
Wave spawnerSends bigger, tougher waves with a break between themServer loop, ServerStorage template, PivotToThis page
Zombie AIWalks at the nearest player and hits in rangeHumanoid:MoveTo, SetNetworkOwnerThis page and NPC pathfinding
Guns and ammoServer-checked shots, limited magazines, reloadsTool, RemoteEvent, workspace:RaycastGun script
MeleeA last resort when ammo runs outTool, GetPartBoundsInBoxSword script
Barricades and doorsBoarded windows to repair, doors players pay to openProximityPrompt, attributesDoor script
Cash and shopCash per kill, weapons and perks to buyleaderstats, server-checked purchasesShop GUI
RevivesA downed teammate can be helped upProximityPrompt with HoldDurationThis page
Rounds and game overStart, wave counter, everyone down, back to lobbyServer stateRound system
Day and night (open world)Safer days, dangerous nightsLighting.ClockTimeDay and night cycle
Inventory (open world)Scavenged items and crafting materialsSaved slots, GUIInventory

The hard part: running a horde on the server

A horror game has one monster; a zombie game may have 25 at once, each a character model with a Humanoid. The decisions that keep that affordable:

  • Cap the number alive. The wave can be 60 zombies long, but only 25 are on the map at once. The rest spawn as others die. Players feel the size of the wave without the server paying for all of it.
  • Chase in a straight line. Each zombie calls Humanoid:MoveTo toward the nearest player a few times a second. No path computing. In a zombie game, a zombie stuck on a barricade is not a bug, it is the barricade working. Use pathfinding only for special zombies that must find a way round.
  • Let the server own them. SetNetworkOwner(nil) on each zombie's root part stops ownership switching to nearby players, which causes stutter and lets a player's device decide where zombies are.
  • Clean up. Destroy dead zombies a few seconds after they fall. Dozens of bodies a wave add up.
  • Spawn out of sight. Spawn points behind the map's windows and doors, not in the open, so zombies arrive instead of appearing.

Build plan: from a baseplate to launch

  1. A starting room. A small building with three or four windows, each with a boarded barricade, and an outside area where zombies spawn. Add a ZombieSpawns folder of invisible parts outside the windows.
  2. A zombie. Make a rig, rename it Zombie, give it a green look and put it in ServerStorage. Check its root part is not anchored.
  3. Waves. Add the ZombieWaves script. Stand in the room with no weapon and watch the waves arrive and grow.
  4. One weapon. A pistol from the gun guide with limited ammo. Pay cash for kills (the gun script deals the damage; give cash when a zombie's Humanoid dies to the player who hit it last).
  5. Barricades. Boards that zombies break by standing at them, and a hold prompt that lets players rebuild them for a little cash.
  6. First playable and test. Ten waves, four players. Watch whether the team spreads out to cover windows or bunches in a corner, and when they first run low on ammo.
  7. Doors and a wall shop. Paid doors into new rooms with better weapons on the walls. This turns the map into a progression.
  8. Launch features. Revives, a game over screen with the wave reached, a highest-wave leaderboard, a lobby, two zombie types beyond the basic one, and the maturity questionnaire.

Escalating waves and the zombie chase

One server script runs the whole horde. Each wave has more zombies (6 plus 4 per wave), more health (60 plus 15 per wave) and a little more speed, capped at 16 so a zombie never outruns a walking player. Each zombie walks at the nearest living player and hits when close.

Script in ServerScriptService named ZombieWaves
-- Script in ServerScriptService named ZombieWaves.
-- Spawns bigger, tougher waves of ServerStorage.Zombie at the parts in
-- Workspace.ZombieSpawns. Each zombie walks at the nearest living player.
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local template = ServerStorage:WaitForChild("Zombie") :: Model -- a rig with a Humanoid
local spawns = workspace:WaitForChild("ZombieSpawns") :: Folder
local MAX_ALIVE = 25 -- zombies on the map at once; the rest wait their turn
local HIT_DAMAGE, HIT_RANGE, HIT_COOLDOWN = 10, 4, 1
local alive = 0

local function nearestPlayer(from: Vector3): (BasePart?, Humanoid?)
	local best, bestHumanoid, bestDistance = nil, nil, math.huge
	for _, player in Players:GetPlayers() do
		local character = player.Character
		local root = character and character:FindFirstChild("HumanoidRootPart")
		local humanoid = character and character:FindFirstChildOfClass("Humanoid")
		if root and root:IsA("BasePart") and humanoid and humanoid.Health > 0 and (root.Position - from).Magnitude < bestDistance then
			best, bestHumanoid, bestDistance = root, humanoid, (root.Position - from).Magnitude
		end
	end
	return best, bestHumanoid
end

local function spawnZombie(health: number, speed: number)
	local points = spawns:GetChildren()
	local zombie = template:Clone()
	local humanoid = zombie:FindFirstChildOfClass("Humanoid") :: Humanoid
	local root = zombie:FindFirstChild("HumanoidRootPart") :: BasePart
	humanoid.MaxHealth, humanoid.Health, humanoid.WalkSpeed = health, health, speed
	zombie:PivotTo((points[math.random(#points)] :: BasePart).CFrame + Vector3.new(0, 3, 0))
	zombie.Parent = workspace
	root:SetNetworkOwner(nil) -- the server moves zombies, so no player can drag them
	alive += 1
	humanoid.Died:Once(function()
		alive -= 1
		task.delay(3, zombie.Destroy, zombie)
	end)
	local nextHit = 0
	while humanoid.Health > 0 and zombie.Parent do
		local target, victim = nearestPlayer(root.Position)
		if target and victim then
			humanoid:MoveTo(target.Position) -- straight line: walls and barricades stop it
			if (target.Position - root.Position).Magnitude < HIT_RANGE and os.clock() > nextHit then
				victim:TakeDamage(HIT_DAMAGE)
				nextHit = os.clock() + HIT_COOLDOWN
			end
		end
		task.wait(0.25)
	end
end

local wave = 0
while true do
	task.wait(15) -- break between waves: repair, buy, regroup
	wave += 1
	workspace:SetAttribute("Wave", wave)
	for _ = 1, 6 + wave * 4 do -- more zombies each wave, each a little tougher and faster
		while alive >= MAX_ALIVE do
			task.wait(1)
		end
		task.spawn(spawnZombie, 60 + wave * 15, math.min(10 + wave * 0.5, 16))
		task.wait(0.5)
	end
	repeat
		task.wait(1)
	until alive == 0
end
  • MAX_ALIVE is the cap from the section above. Raise it only after testing your biggest wave on a real server with a full team.
  • Each zombie runs its own small loop four times a second. MoveTo stops on its own after 8 seconds without reaching the goal, so the loop calls it again well before that.
  • TakeDamage does nothing while the player has a ForceField, so players who just respawned are briefly safe.
  • The script never ends a run: dead players respawn and keep fighting. For a real game over, stop respawns during a wave (or use downed players, below), and when no player is left alive, destroy the zombies, show the wave reached and reset.
  • For new zombie types, read a type from a list per wave: a runner with high speed and low health, a tank with lots of health and a slow walk, both from different templates in ServerStorage.
Screenshot from a Roblox Studio playtest: a round timer banner in the candy theme.
Studio screenshot. The round timer from RoCode's UI kits (candy theme), in a Studio playtest. A kit screen RoCode can add, for example to show the wave and the break, not part of a game built in this guide.

Revives: the system that makes it co-op

Without revives, a player who dies early watches the rest of the round. With them, a downed player is a problem the team has to solve under pressure, and those are some of the tensest moments a round can have. A simple version: when a player's health would hit zero, the server sets a Downed attribute instead, slows them to a crawl, and puts a ProximityPrompt with a HoldDuration of a few seconds on them. A teammate who holds it to the end brings them back with some health. If nobody comes in time, they die and respawn next wave.

Do the downed check on the server: keep the Humanoid's health above zero by handling damage yourself (for example in the same place your zombies and weapons call TakeDamage), rather than trying to undo a death after it happens.

Monetization that fits zombie survival

In a co-op PvE game, nobody loses a fight to another player's purchase, so power is easier to sell than in a shooter or a fighting game. The risk moves elsewhere: if a purchase makes the game trivial, the buyer gets bored, and if the team expects one person to carry, everyone else feels useless.

What fits a zombie survival game, and the trap in each
ItemRoblox featureAccepted?Watch out for
Starting weaponPassYesA strong gun at wave 1 skips the early game. Make it better than the free pistol, not better than the wall guns.
Self-reviveDeveloper productYesLimit it per match, or the team stops reviving each other.
Cosmetics (skins, outfits, kill effects)Pass or developer productYesNone.
More ammo or inventory slotsPassMixedAmmo scarcity is a main source of tension. A little extra is fine; unlimited removes the game.
Private serverPrivate serversYesSquads want to play with people they trust.
Watch an ad for a bonusRewarded video adsOnly if eligibleRewards must be developer products. Roblox says ads should not harm the character during play, so offer them in the lobby or between waves, never mid-wave.

Passes are one-time purchases; developer products can be bought again, so self-revives and ammo refills are developer products. See the game pass guide for checking ownership on the server.

What brings zombie survival players back

  • Highest wave. A leaderboard of the best wave per team or per player is the genre's main goal. Show the record on the game over screen.
  • New maps. Each map is a new puzzle of windows, doors and choke points. A map with a secret (a hidden weapon, a way to end the waves) gives players something to discover.
  • Progression between matches. Levels that unlock new starting loadouts or cosmetics give a reason to play even a run that ends at wave 8.
  • Zombie variety. Each update adds a zombie that breaks an old strategy.
  • Open world later. Scavenging, crafting and a saved base turn a round-based game into one players live in. It is a big step; ship waves first.

For a single, smarter enemy instead of a horde, see the horror game guide; for defending a path with placed units instead of guns, see the tower defense guide.

Build it with RoCode

RoCode is an independent AI agent for Roblox Studio, not made by Roblox. You describe the game in a web chat and its Studio plugin writes the Luau and builds parts, scripts and UI in the place you have open. For a zombie game it can build the starting room and spawns, the wave and zombie scripts, weapons with server checks, barricades and doors, and add a HUD, a round timer and a shop from its UI kits. It can also build a themed world island, such as a snow or desert canyon area, in one call. It cannot make zombie meshes or animations.

You type

Make the first playable version of a zombie survival game in my place: a small building with 4 boarded windows, zombie spawn points outside, a Zombie rig in ServerStorage, waves that grow in count, health and speed with a 15 second break, at most 25 zombies alive, a pistol with limited ammo, cash per kill in leaderstats and a wave counter on screen.

RoCode does
  • Writes the wave, zombie, weapon and barricade scripts with damage and cash decided on the server
  • Builds the starting room and spawn points, then adds doors, a shop and revives in rounds
  • Can add UI kit screens such as a shooter HUD, a round timer, a shop and notifications
  • Can run a test robot that walks, equips a tool and reports PASS or FAIL on what it checked

Build this in Studio

RoCode does not publish the game or spend Robux, and it cannot say whether wave 20 is fun. The free plan gives free credits every day, no card needed. How RoCode builds a game.

Questions

How do I make zombies chase players in Roblox?

Give each zombie a Humanoid, make the server its network owner, and a few times a second call Humanoid:MoveTo toward the nearest living player. The wave script does this. Use pathfinding only for zombies that must find their way around walls.

How many zombies can a Roblox server handle?

It depends on your zombie models, scripts and map, so measure rather than guess. Start with a cap of around 25 alive at once, test your largest wave on a real server with a full team, and raise it only if the game stays smooth.

How do I make zombie waves harder?

Raise several things together: zombie count, health and speed, and add new zombie types every few waves. Raising only health makes waves longer, not harder.

Can I make a zombie game without scripting?

The map and barricades can be built with parts, but waves, zombie AI, guns and cash need scripts. You can paste the scripts from this page and the gun guide, or describe the game to RoCode and let it write them.

Is selling a strong gun pay to win in a zombie game?

Less so than in PvP, because no other player loses to it. It can still hurt the game by making early waves trivial for the buyer, so make paid weapons a head start rather than the best weapon in the game.

Sources and further reading

How the code was checked: every script on this page passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 26 October 2026). A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.

Try RoCode on your own place.

Free every day, no card required. Install the plugin, describe the feature, and review what lands in Studio.