In short
An asymmetric game is a round with two roles. The server picks one killer, preferably with a chance that grows each round a player is not picked, and puts everyone else on the Survivors team with a head start. Survivors complete objectives, such as repairing generators with a hold prompt, which open an exit. The killer wins by taking every survivor out before the exit opens or the timer ends. Dead survivors spectate, and the next round starts after a short intermission.
- Balance is three numbers: killer speed against survivor speed, how long objectives take, and how big the map is. Change one at a time.
- Do every hit check on the server. A killer's attack that only the client checks can be fired from anywhere.
- Give dead survivors something to do, or they leave and the next round has fewer players.
On this page
What makes a killer vs survivors game work
The loop in one line: survivors split up to finish objectives while the killer hunts them; the round ends in an escape or a wipe. Each round is a short story with a beginning (the head start), a middle (chases) and an end (the exit opening or the last survivor caught).
| Time scale | Survivor | Killer |
|---|---|---|
| Every 10 seconds | Repairs, listens, watches for the killer, runs | Searches, follows sounds and tracks, attacks |
| Every minute | A generator finished, a chase escaped, a teammate saved | A survivor downed, a generator area patrolled |
| Every round (a few minutes) | Escape or die, then spectate | Wipe the group, or lose them at the exit |
| Every session | Currency for new survivors and skins | Currency for new killers and abilities |
The games that last get three things right. First, both roles are fun: if the killer always wins, survivors quit, and if the killer always loses, nobody wants the role. Second, the killer pick feels fair: players who wanted to be killer for ten rounds and never were will leave. Third, chases have counterplay: obstacles survivors can loop around or block, places to hide, and abilities with cooldowns, so a chase is a contest instead of a straight line the faster player always wins.
The systems you need
| System | What it does | Roblox pieces | Guide |
|---|---|---|---|
| Rounds | Intermission, map, round timer, results | Script, workspace attributes | Round system |
| Roles and teams | Picks the killer, puts others on Survivors | Teams, Team, SpawnLocation | Team system |
| Killer attack | A melee hit checked on the server | Tool, server hitbox, Humanoid:TakeDamage | Combat, Sword |
| Objectives | Generators repaired with a hold prompt | ProximityPrompt, CollectionService, attributes | This page |
| Exit | Opens when objectives are done | Parts, Touched | This page |
| Stamina and sprint | Short bursts of speed for chases | Humanoid.WalkSpeed, UserInputService | Sprint |
| Health and downs | Health bars, a downed state | Humanoid, BillboardGui | Health bar |
| Spectating | Dead survivors watch the living | Camera.CameraSubject, LocalScript | This page |
| Unlocks and saving | Currency for new characters and skins | DataStoreService | DataStore tutorial |
Build plan: from a baseplate to launch
First playable (greybox)
- In the Teams service add three Team objects: Lobby (AutoAssignable on), Survivors and Killer (AutoAssignable off), each with its own TeamColor.
- Build a lobby and one map from grey parts: walls with gaps to loop around, a few rooms, four generator parts tagged
Generatorand a part namedExitGate. Add a SpawnLocation for each team with Neutral off and the matching TeamColor. - Add the two scripts below: the round with the killer pick, and the generators with the exit.
- Give the killer a melee tool from the sword guide, with the hit checked on the server.
- Play a local server test with 4 players in the Test tab. Check the round ends when the killer wins, when survivors escape and when the killer leaves.
First public test
- Add a round timer on screen, a results screen and spectating for dead survivors.
- Add sprint with stamina for survivors and a slightly faster base speed for the killer.
- Publish and watch win rates by role over many rounds. If one side wins far more often, adjust one number and test again.
Before launch
- Two or three killers with one ability each (a dash, a trap, a short reveal of survivors) and survivors with one ability each (a heal, a speed burst, a decoy), all on server-checked cooldowns.
- A second map, chase music that gets louder near the killer, and a currency earned every round.
- Saving, a shop for characters and skins, and AFK handling so an idle killer does not ruin a round.
A fair killer pick and the round
Each player has a KillerChance attribute starting at 1. Every round they are not picked, it goes up by 1; the killer's resets to 1. The pick is weighted by that number, so it is still random, but a player who has waited six rounds is far more likely to be next than one who just played killer. Survivors spawn first, and the killer waits in the lobby for the head start.
-- Script in ServerScriptService named KillerRound.
-- Picks a killer with a chance that grows each round you are not picked, gives
-- survivors a head start, and ends when no survivor is left in the round.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")
local ROUND_SECONDS = 240
local HEAD_START = 15
local killerTeam = Teams:WaitForChild("Killer") :: Team
local survivorTeam = Teams:WaitForChild("Survivors") :: Team
local lobbyTeam = Teams:WaitForChild("Lobby") :: Team
local function chance(p: Player): number
return tonumber(p:GetAttribute("KillerChance")) or 1
end
local function pickKiller(players: { Player }): Player
local total = 0
for _, p in players do
total += chance(p)
end
local roll = math.random() * total
for _, p in players do
roll -= chance(p)
if roll <= 0 then
return p
end
end
return players[#players]
end
local function playRound(players: { Player })
workspace:SetAttribute("Escaped", 0)
workspace:SetAttribute("ExitOpen", false)
for _, gen in CollectionService:GetTagged("Generator") do
gen:SetAttribute("Progress", 0)
end
local killer = pickKiller(players)
for _, p in players do
if p == killer then
p:SetAttribute("KillerChance", 1)
p.Team = lobbyTeam -- the killer waits in the lobby during the head start
else
p:SetAttribute("KillerChance", chance(p) + 1)
p.Team = survivorTeam
p:LoadCharacterAsync() -- spawns at the team's SpawnLocation
local humanoid = p.Character and p.Character:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Died:Connect(function()
p.Team = lobbyTeam -- out of the round: respawns in the lobby to watch
end)
end
end
end
workspace:SetAttribute("Status", "Hide! The killer arrives in " .. HEAD_START .. " seconds")
task.wait(HEAD_START)
killer.Team = killerTeam
killer:LoadCharacterAsync()
local endsAt = os.clock() + ROUND_SECONDS
while os.clock() < endsAt and #survivorTeam:GetPlayers() > 0 and killer.Parent do
workspace:SetAttribute("TimeLeft", math.ceil(endsAt - os.clock()))
task.wait(1)
end
local escaped = tonumber(workspace:GetAttribute("Escaped")) or 0
local survived = escaped + #survivorTeam:GetPlayers()
workspace:SetAttribute("Status", if survived > 0 then survived .. " survived" else "The killer wins")
for _, p in Players:GetPlayers() do
p.Team = lobbyTeam
p:LoadCharacterAsync()
end
end
while true do
task.wait(20) -- intermission
local players = Players:GetPlayers()
if #players >= 2 then
playRound(players)
end
end
A survivor who dies moves to the Lobby team, so they respawn there to spectate, and the round loop only has to count the Survivors team. The round ends when that team is empty (everyone escaped or died), the timer runs out, or the killer leaves the game. For the intermission screen and map voting, the round system guide goes further.
Generators and the exit
Each generator takes 10 holds of 1.5 seconds, so a lone survivor needs at least 15 seconds of uninterrupted work, and the killer has time to notice. Letting go only loses the current hold. Only players on the Survivors team can repair, and when every generator reaches 100 the exit opens.
-- Script in ServerScriptService named Generators.
-- Survivors repair parts tagged "Generator" a step at a time. When every one is
-- done, the part named ExitGate opens and survivors who touch it escape.
local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")
local STEP = 10 -- progress per finished hold, out of 100
local survivorTeam = Teams:WaitForChild("Survivors") :: Team
local lobbyTeam = Teams:WaitForChild("Lobby") :: Team
local exitGate = workspace:WaitForChild("ExitGate") :: BasePart
local function allDone(): boolean
for _, gen in CollectionService:GetTagged("Generator") do
if (tonumber(gen:GetAttribute("Progress")) or 0) < 100 then
return false
end
end
return true
end
local function setUpGenerator(gen: Instance)
if not gen:IsA("BasePart") then
return
end
local prompt = Instance.new("ProximityPrompt")
prompt.ActionText = "Repair"
prompt.HoldDuration = 1.5 -- let go and you lose only the current step
prompt.Parent = gen
prompt.Triggered:Connect(function(player: Player)
local progress = tonumber(gen:GetAttribute("Progress")) or 0
if player.Team ~= survivorTeam or progress >= 100 then
return -- only survivors repair, and only unfinished generators
end
gen:SetAttribute("Progress", math.min(progress + STEP, 100))
if allDone() then
workspace:SetAttribute("ExitOpen", true)
end
end)
end
for _, gen in CollectionService:GetTagged("Generator") do
setUpGenerator(gen)
end
CollectionService:GetInstanceAddedSignal("Generator"):Connect(setUpGenerator)
exitGate.Touched:Connect(function(hit: BasePart)
local character = hit.Parent
local player = if character and character:IsA("Model") then Players:GetPlayerFromCharacter(character) else nil
if player and player.Team == survivorTeam and workspace:GetAttribute("ExitOpen") == true then
player.Team = lobbyTeam
workspace:SetAttribute("Escaped", (tonumber(workspace:GetAttribute("Escaped")) or 0) + 1)
player:LoadCharacterAsync() -- back to the lobby, safe from the killer
end
end)
- Show progress with a
BillboardGuiover each generator that reads itsProgressattribute, and show the killer a flash when a generator finishes. - Two survivors on one generator finish it twice as fast with this script, which rewards teamwork. If that makes rounds too short, lower
STEPso each generator needs more holds. - More generators than are needed (for example five, with four required) stops the killer from guarding the last one.
Balancing one against many
Characters walk at 16 studs per second by default. A killer at exactly survivor speed never catches anyone in the open, and a much faster killer ends every chase in seconds. One approach is a small speed edge for the killer, balanced by survivor tools: sprint bursts with stamina, obstacles to loop and doors to close. Tune with these levers, one at a time:
| Lever | Raise it and... | Watch for |
|---|---|---|
| Killer speed | Chases end sooner; killer wins more | Survivors who feel nothing they do matters |
| Objective time | Rounds last longer; killer has more time | Survivors bored holding a prompt |
| Map size | More hiding; harder for the killer to find anyone | Rounds where nothing happens |
| Head start | Survivors spread out before the hunt | A first minute with no tension |
| Survivor count per killer | More objectives done in parallel | One killer cannot pressure everyone; consider two killers in big servers |
Set Max Players for the round you designed. Write down how many players a round is meant for, and test at that size, at the smallest size you allow, and at full.
Monetization that fits the genre
| Product | Roblox feature | Fits the genre? |
|---|---|---|
| Killer and survivor skins | Pass or developer product | Yes. The genre's main purchase: looks, same stats. |
| New characters | Currency earned in rounds, or a pass | Yes, if each is a sidegrade (different, not stronger) and earnable without paying. |
| Killer chance boost | Developer product | Can fit, if you say exactly what it does in numbers. It lowers everyone else's chance too, so keep it small. |
| Stronger abilities or more health | Any | No. One paid killer with more speed decides every round they play. |
| VIP server | Paid private servers | Yes. Friends want to play rounds together. |
| Monthly perks | Subscription | Can fit: a monthly skin and bonus currency, honoured for the full term. |
Keep paid perks out of the round itself. A purchase that makes a killer faster or a survivor tougher shows up in every round that player is in, and the other side notices quickly. Rewarded video ads, if your game is eligible, belong in the lobby between rounds; Roblox's rules say the ad should not harm the player's character, and an ad during a chase would.
What brings players back
- Unlocks. Currency every round, spent on new killers, survivors and skins, is the main long-term goal.
- New killers and maps. Each new killer changes how every map plays. The genre's updates are characters.
- Daily quests. "Repair 5 generators", "Escape twice", "Win as killer once" push players to try both roles.
- Social play. Escaping with friends is the best moment the genre has. Make joining friends easy and give private servers a reason to exist.
- Daily rewards with a streak, paid in the round currency.
Build it with RoCode
RoCode is an AI agent that builds in the Roblox Studio place you have open: you describe the game in a web chat and its free Studio plugin creates the scripts, parts and UI. For a killer vs survivors game it can set up the teams, the round loop with a fair killer pick, generators and an exit, and a killer melee tool with server hit checks, and add UI kit screens such as a round timer, a shooter style HUD or health bars. It cannot make killer models or attack animations, and it cannot tell you whether the balance is fun; that takes real rounds with real players. A full game is built in rounds, one working part at a time.
Make the first playable of a killer vs survivors game: Lobby, Survivors and Killer teams, a round every 20 seconds that picks a killer with a chance that grows each round you are not picked, a 15 second head start, 4 generators survivors repair with a hold prompt, an exit that opens when all are done, and a killer sword with server hit checks.
- Creates the teams, spawns, generators and exit, and writes the round and objective scripts
- Can add UI kit screens such as a round timer, health bars and notifications
- Can run a test robot that walks to a generator and holds the prompt, and report PASS or FAIL
- Takes screenshots in edit mode to check the map layout
You still balance it by playing many rounds with real people. How RoCode builds a game in rounds.
Questions
How do you make a killer vs survivors game on Roblox?
Build a round loop that picks one killer and puts the others on a Survivors team, give survivors objectives that open an exit, give the killer a server-checked attack, and end the round on an escape, a wipe or the timer.
How do I pick the killer fairly?
Use a weighted pick: each player has a chance value that grows every round they are not the killer and resets when they are. It stays random but stops long droughts.
How many players does an asymmetric game need?
At least two to run a round, but it plays as designed only at the size you balanced for. Test at your smallest and largest server sizes, and consider two killers in big servers.
Should the killer be faster than survivors?
Usually a little, with survivors given sprint bursts, obstacles and hiding places to make up for it. Equal speed makes chases endless; much faster makes them pointless.
Can I make this game without scripting?
No: rounds, roles, objectives and hits all need scripts. You can start from the scripts on this page, or describe the game to an AI agent such as RoCode and test what it builds.
Sources and further reading
- Roblox Creator Docs: Teams
- Roblox Creator Docs: SpawnLocation. Neutral and TeamColor
- Roblox Creator Docs: Player:LoadCharacterAsync
- Roblox Creator Docs: ProximityPrompt
- Roblox Creator Docs: Humanoid.WalkSpeed
- Roblox Creator Docs: Passes
- Roblox Creator Docs: Private servers
- Roblox Creator Docs: Rewarded video ads
- RoCode guide: Round system
- RoCode guide: Team system
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.