How To Make A Random Map Picker

Hello guys in this tutorial I plan on teaching you how to make a successful random map picking script which will do the following:

1.) choose a random map
2.) load the random map
3.) teleport all of the players to a certain spot on the map and back
4.) destroy the map when finished
5.) repeat the cycle of steps 1-4

Getting Started

The first thing we are going to want to do is of course make our maps, when you are done with them make sure to group all of them and call the model “Maps.” (Make sure to make a lobby in Workspace) it doesn’t have to be a model, you may make it a folder as well, but make sure to parent the model/folder to ServerStorage. In those maps make sure to add a part and name it “Spawn,” this will be where we want the character to spawn on the map. Next you will want to add a folder into workspace and name it “CurrentMap.” Finally the last thing we need to make is to add a (Server)Script in ServerScriptService and add a StringValue named “ChosenMap” as a child of that script. At the end of this your set up should look like this:

Random Map Picker - Roblox Studio 2_19_2020 7_31_40 PM

Now that your set up is all done, we can start getting into the main part you guys probably wanted to know, the actual script.

First thing we are going to put into our script is to define all of the necessary things needed to make this script work, so that way it is easier and cleaner. Make sure you define the maps, currentmap folder, chosenmap stringvalue, and our spawn back to the lobby. As for players, we will need to define them in our teleport function, so that way it can grab everyone appropriately. When you are done your script should end up like this:

local maps = game.ServerStorage.Maps:GetChildren()
local currentmap = workspace:WaitForChild("CurrentMap")
local chosenmap = script:WaitForChild("ChosenMap")
local spawner = workspace.Lobby:WaitForChild("Spawn") -- match this to your path of your lobby spawner

Messing With The Maps

Now that we have finished defining everything, lets get into our map chooser, this will choose a random map and save its name to the stringvalue we have called “ChosenMap.” In this we are going to create a function and name it chooseMap(), in this function we will use a for loop to look at all of the maps we have in ServerStorage then adding it to a table and checking to see if it is a model just in case. After we have added all of the maps to the table, we will pick a random one using math.random and set our stringvalue to the name of that map. This is how I set up my function:

function chooseMap()
    local choices = {}
    for i = 1, #maps do
        if maps[i]:IsA("Model") then
            table.insert(choices, maps[i])
    local picked = math.random(1,#maps)
    chosenmap.Value = choices[picked].Name

Next we need to actually load the map into workspace and then delete it when the round is over. I am pretty sure you know what we are going to do for loading the map, yep we are going to clone it into our “CurrentMap” folder by using the value in our “ChosenMap” stringvalue. As for deleting the map we simply search for our “CurrentMap’s” folder and if it is a model, that being our current map, we will destroy it. Here is how I set this up:

function loadMap()
	local map = game.ServerStorage.Maps:FindFirstChild(chosenmap.Value):Clone()
	map.Parent = currentmap

function deleteMap()
	for i,v in pairs(currentmap:GetChildren()) do
		if v:IsA("Model") then

Teleporting The Players And Finishing Everything Up

Now here comes probably the hardest part of this script, teleporting the players to the map and back. This is, as I have said up top, where we will need to define all of the players in the server. When teleporting the player you can use MoveTo() for their character, but I feel it is just easier to find the HumanoidRootPart and set its CFrame to our spawns CFrame on the map that has been chosen. When we are teleporting the player back, it is the same thing, except always having the HumanoidRootPart’s CFrame change to the spawn’s CFrame in the lobby. Here is how I set this up:

function teleportPlayers()
	local players = game.Players:GetPlayers()
	for i,v in pairs(players) do
		v.Character.HumanoidRootPart.CFrame = currentmap:FindFirstChild(chosenmap.Value).Spawn.CFrame

function teleportBack()
	local players = game.Players:GetPlayers()
	for i,v in pairs(players) do
		v.Character.HumanoidRootPart.CFrame = spawner.CFrame

Now that all of our functions are set up, we need to call them at the correct time for the script to actually work. We will make a while loop so the script will repeatedly run and in this set the times we want the functions to be called. Change this to your set up, mine is probably different then what yours will be:

while true do


I hope this long tutorial was helpful! If you had a hard time trying to understand some things or had a hard time creating this script, you can take a look at this downloadable file so you can look over and review it: Random Map Picker.rbxl (22.4 KB)

Thanks For Reading I Hope This Was Helpful! :grin:


FYI: In math.random you can give one argument and it’ll produce a number between [1, n]

For example:

local picked = math.random(#maps)

Nice tutorial anywho.


Adding onto what @ReturnedTrue said, you can just index from the choices table instead of using local picked = math.random(1,#maps).

    local picked = choices[math.random(#maps)]
    chosenmap.Value = picked.Name

Based on my previous mistakes and some posts that I’ve read - I would like to advice to load bigger maps piece by piece, otherwise it’ll lag the server for a moment. Referring to How should I handle loading maps? - #4 by Ruben_Zanzus

Like so:

local ServerStorage        = game:GetService("ServerStorage")
local MapsFolder           = ServerStorage.Maps

---//Choose map function 
local ChosenMap            = MapsFolder[math.random(#MapsFolder)]

function loadMap()
--//Send the clients a message that the map is loading (Perhaps a notification UI?)
          for Index, Part in pairs(Chosenmap:GetChildren()) do 
            v:Clone().Parent = workspace.CurrentMap --//Assuming you have a CurrentMap folder in the workspace
--//Send the clients a message that the map is ready

Also I’d use the event :ClearAllChildren() for the map removal


Thanks for the tutorial! It was very helpful. But can you do a tutorial for making a round-based system? Would be appreciated if you do, thanks!


While using a random value between 1 and n is the correct thinking, math.random tends to have pretty bad results if using for something you want to actually appear a little random. I recommend that you use the Random object.

The Random datatype and math.random have no difference in randomness, they’re both psuedorandom and use the same algorithm.

The only difference is that the Random datatype has it’s own seed per object (since math.randomseed sets it for the entire environment) and that it has functions such as NextNumber/NextInteger.

The Random datatype is great to use, but it isn’t any more random than math.random.


It doesn’t make any sense to yield for so long, especially in the case you are considering (huge maps). For instance, loading a 15,000 parts map would take at least 25 minutes to load, while if you just insert it as a whole could take up to only a few seconds (maybe a minute in very low-end devices if it included large parts or unanchored components).

Also, @HeIIo42bacon, excellent tutorial! I think you explained it so well. Loading maps is essential for a lot of places and genres, so this topic will be for sure very useful for many devs!

I think you could add that changing HumanoidRootPart’s CFrame will overwrite the character’s rotation, while MoveTo will conserve it. This detail might be useful for some gamemodes.

But again, thanks for your contribution!


there are a lot of ways to perform this type of thing but I’d say this is a pretty decent tutorial, good job!

I sometimes get repetitive behavior from calls to math.random so I usually do something like this:

local Maps = { --[[ maps ]] }
local RandInstance =

function GetRandomMap(MapsTable, RandomIndex)
     return MapsTable[RandomIndex]

GetRandomMap(Maps, RandInstance:NextInteger(0, #Maps)) -- Call on Maps table w/ random index between 0 and length of table

Decrease the wait to your liking and tailor it to your game. The whole reply was focused on advising against instantaneous map loading. I sent a link to the post that explains (specifically the reply section) the reason why that is a bad idea, have a read.


You could make this a lot more efficient by picking the map straight from the Maps in ServerStorage. Using recursion, you can also make sure that the map that got picked isn’t the same map as the last map.

local maps = game.ServerStorage.Maps:GetChildren()
local lastMap = nil

function chooseMap()
  local picked = maps[math.random(1,#maps)
  if picked.Name == lastMap then return chooseMap() end
  chosenmap.Value = picked.Name
  lastMap = picked.Name

Hey everyone! Thanks for all of the feedback you gave on how to improve this script! I have made a video tutorial that combines some of your ideas together. You can check it out here:

Sorry if this video was a little hard to understand, I messed some things up a bit and kind of wasn’t thinking well that day lol. Anyways enjoy, I hoped this helps! :slightly_smiling_face:

Edit: Also I don’t know if I should set this as a solution, I have seen some people do that, but I feel as if it is not right. Tell me if it is appropriate to solution this though for the tutorial and I will.


I just realised how bad my scripted game cycle is. Amazing tutorial. You made it look easy and cool. Keep it up!

I’m not sure if this is necrobumping, but can you please add a timer so players can see how long it will take before a round ends/starts?

You should check out my other tutorial for that where it fully teaches you how to make a round-based system. It should show you how to set a timer up in there.

Hey Guys, so I am very new to scripting and stuff. I have a map with JTOH [jukes towers of hell] client objects in them but this map picker makes the client objects break can anyone help thankyou. because of the heavy requirements to be able to make posts i have to reply to get help its really annoying.

1 Like