Tutorials•November 8, 2026•8 min read

Roblox math.random: Numbers, List Choices, and Repeatable Tests

Use Roblox math.random for integer and decimal ranges, choose from arrays safely, handle empty lists, and understand repeatable Random generator tests.

In Roblox, math.random produces pseudorandom numbers. Its arguments change the kind of result you receive: a decimal with no arguments, or an integer when you provide integer bounds. For a game feature, start by deciding whether you need a numbered choice, a continuous value, or a sequence you can reproduce while debugging.

Three random-selection designs: an integer index, a decimal duration, and matching generator state
Original concept diagram for the practice script. The illustrated values are examples, not captured random output.

Choose the right math.random call

The Roblox math reference distinguishes three call forms. Keep the bounds intentional instead of adding rounding to every result.

Random-number forms used in Roblox scripts
CallResultUseful question
math.random()Decimal at least 0 and less than 1What fraction of a range should I use?
math.random(6)Integer from 1 through 6Which of six numbered choices?
math.random(2, 5)Integer from 2 through 5Which allowed whole-number value?

The upper endpoint matters. A six-sided practice die can return 6. A no-argument fraction stays below 1. Do not assume that every random API has identical endpoint behavior; read the particular method you are using.

Run a complete checkpoint-choice exercise

Insert a regular Script in ServerScriptService in a practice place, open Output, and run this code. It selects checkpoint names and prints numbers. It does not create checkpoints, move a player, grant rewards, or change saved progress.

local checkpoints = {"Garden", "Tower", "Bridge"}

local function chooseCheckpoint(names)
    if #names == 0 then
        return nil
    end
    local index = math.random(1, #names)
    return names[index]
end

local unitValue = math.random()
local die = math.random(1, 6)
local duration = 0.5 + math.random() * 2
print("Unit value:", unitValue)
print("Die:", die)
print("Duration:", duration)
print("Chosen checkpoint:", chooseCheckpoint(checkpoints))
print("Empty list handled:", chooseCheckpoint({}) == nil)

local source = Random.new(31415)
local replay = source:Clone()
for draw = 1, 3 do
    local first = source:NextInteger(1, 6)
    local second = replay:NextInteger(1, 6)
    print("Aligned draw:", draw, first, second, first == second)
end

-- The source and clone advance independently.
-- Keep their draw counts aligned when comparing their sequences.
source:NextInteger(1, 6)
print("Source advanced once more without advancing replay")

Each run can show different numbers and a different checkpoint name. Check the properties instead of comparing the output with one invented random transcript: the unit value is at least 0 and below 1, the die is an integer from 1 through 6, and the duration is at least 0.5 and below 2.5. The chosen name belongs to the three-item list.

The empty-list check should print true. The three aligned generator comparisons should also print true. Those are predicted properties based on the code and documentation, not captured Studio results. This example has been documentation-reviewed but has not been executed here in Roblox Studio.

Convert a fraction into a decimal range

The duration expression starts at 0.5 and adds a fraction of a two-unit span. Read it as minimum + fraction * (maximum - minimum). It is a numeric exercise; connecting it to a timer is a separate step.

Do not pass decimal bounds to an integer-selection form and expect a continuous range. Also avoid rounding the duration immediately if the feature actually needs fractional timing. Rounding changes the available outcomes and can hide the difference between a decimal range and a whole-number choice.

For an object with its own generator state, the Random reference provides NextInteger and NextNumber. Choose the method according to the value the feature needs. Check that method’s documented bounds rather than copying assumptions from math.random.

Pick from a compact array and handle an empty list

The chooser samples a valid position in a compact array. Its guard runs before selecting an index, so an empty list returns nil without attempting to draw from a nonexistent range. The caller then decides what no selection means.

This example assumes a contiguous sequence with no nil holes. A dictionary of named settings is a different structure. If your list is built dynamically, validate its shape and remove unavailable entries deliberately. The Roblox tables guide explains arrays, dictionary keys, holes, insertion, and removal.

A name is also different from a live Instance. If you adapt the exercise to choose actual objects, verify that the selected object still exists and belongs to the allowed set when the action occurs. Choosing a valid list position does not establish that a later game action is valid.

Expect repeats unless the design removes them

Picking an index again can select the same checkpoint as the previous draw. A repeat alone does not show that the generator is broken. Decide whether the feature allows replacement before changing the code.

If each checkpoint must appear once in a round, represent that requirement with a remaining-items list or a deliberately shuffled order. If only immediate repeats are forbidden, exclude the previous choice from the next candidate set. Those are different game rules; neither follows automatically from calling a random function.

Small samples also look uneven. Three draws are useful for reading the program’s behavior, but they cannot prove that every possible outcome appears equally often or that a game’s overall reward system is fair.

Use generator state to reproduce a debugging sequence

The final section creates a Random object, then clones its current state. Matching methods, arguments, and draw counts let the example compare aligned results. The clone advances separately, so consuming an extra value from one generator changes which positions you compare next.

Record the setup and the order of draws when investigating a bug. A seed by itself is not a complete record of a feature that conditionally consumes different numbers of random values. A branch that draws one extra time can shift every later comparison.

The exercise does not assert that two unaligned values must differ. Different sequence positions can happen to produce the same number. Use the sequence position and program state to reason about the test, rather than treating inequality as proof of independence.

Avoid resetting state inside every selection

Creating a fixed-seed generator inside the chooser would restart its sequence on each call. That would undermine the intended idea of drawing successive choices. Construct the generator at the lifetime your feature needs, then reuse it for that feature’s draws.

Similarly, do not add repeated seeding as a reflexive fix for an unexpected duplicate. First inspect the bounds, candidate count, list contents, and where generator state is created. For reusable helpers, the ModuleScript guide shows how API state and independently constructed instances differ.

Keep the game decision on its authoritative side

This practice script runs on the server, but printing a random name is only a learning exercise. A production feature still needs rules about when a choice may happen, who can request it, and which choices are allowed. A client-provided random outcome should not become authoritative progress simply because it looks plausible.

Separate selection from its effects. Test a small chooser first, then connect it to your round controller with explicit validation. For event frequency, continue with the debounce and cooldown guide. For timed work, see the task-library comparison. Documentation checked November 8, 2026.

Frequently Asked Questions

Does math.random(1, 6) include 6 in Roblox?▾

Yes. With integer bounds, both endpoints are included. This is different from the no-argument form, whose result is below 1.

How do I choose a random item from a Roblox array?▾

For a compact nonempty array, draw an integer index from 1 through its length. Handle an empty array before drawing, and keep nil holes out of the sequence.

Why can random choices repeat?▾

A fresh selection can pick an earlier outcome. If repeats are forbidden, implement that rule explicitly with a remaining-items list or an appropriate exclusion rule.

Does cloning a Random object share its advancing state?▾

A clone begins with copied generator state and advances independently. Use matching draw counts, methods, and arguments when comparing the two sequences.

Ready to build your Roblox game?

Create, edit, preview, and export your game for free. No credit card required.

Try Obby — 100% Free →