Why isn’t math.random not random?

Hey! So basically I have a script to make teams random, but it only works once, then its not random anymore how do I make it random? Heres the variable that controls all the randomness

local randTeam = math.random(1,2)

(I used Random.new, it does the same thing)

This variable is used inside the game script, and it only runs when the game starts, to choose the random killer, but the problem is its not random.

This is the entire script


local rep = game:GetService("ReplicatedStorage")
local plrs = game:GetService("Players")
local votingSystem = game.Workspace.Voting
local status = rep.Status

local redTeam = game.Teams["Killer"]
local blueTeam = game.Teams["Runner"]
local blueTeamColor = BrickColor.new ("Lime green")
local redTeamColor = BrickColor.new ("Really red")

local lobbyTeam = game.Teams.Lobby

local choices = votingSystem:GetChildren()
local maps = rep.Maps:GetChildren()

local intermission = 10

local isAnOption
local randomMap

local chosenMap
local mapClone

local BlueTeamCount
local RedTeamCount


-- picking a random map function
local function PickRandomMap ()

	local randomNumber = math.random(1, #maps)

	randomMap = maps[randomNumber]

	return randomMap.CanBeVoted
end


for i, choice in pairs(choices) do

	local name = choice.label.SurfaceGui.TextLabel
	local picture = choice.Image.SurfaceGui.ImageLabel

	isAnOption = PickRandomMap()

	if isAnOption.Value == true then
		repeat 
			wait()
			isAnOption = PickRandomMap()
		until
		isAnOption.Value == false
		name.Text = randomMap.Name
		picture.Image = randomMap.Image.Value
		randomMap.CanBeVoted.Value = true

	else
		name.Text = randomMap.Name
		picture.Image = randomMap.Image.Value
		randomMap.CanBeVoted.Value = true		
	end					
end	


rep.InRound.Changed:Connect(function()

	if rep.InRound.Value == false then

		mapClone:Destroy()

		for i, map in pairs(maps) do
			map.CanBeVoted.Value = false
		end

		for i, choice in pairs(choices) do

			local name = choice.label.SurfaceGui.TextLabel
			local picture = choice.Image.SurfaceGui.ImageLabel

			isAnOption = PickRandomMap()

			if isAnOption.Value == true then
				repeat 
					isAnOption = PickRandomMap()
				until
				isAnOption.Value == false
				name.Text = randomMap.Name
				picture.Image = randomMap.Image.Value
				randomMap.CanBeVoted.Value = true

			else
				name.Text = randomMap.Name
				picture.Image = randomMap.Image.Value
				randomMap.CanBeVoted.Value = true		
			end					
		end	


	else

		-- after the intermission has ended, the round will soon begin
		--- when the map with most votes will be spawned

		local Choice1Votes = #votingSystem.Choice1.button.Votes:GetChildren()
		local Choice2Votes = #votingSystem.Choice2.button.Votes:GetChildren()
		local Choice3Votes = #votingSystem.Choice3.button.Votes:GetChildren()

		if Choice1Votes >= Choice2Votes and Choice1Votes >= Choice3Votes then

			chosenMap = votingSystem.Choice1.label.SurfaceGui.TextLabel.Text

		elseif Choice2Votes >= Choice1Votes and Choice2Votes >= Choice3Votes then

			chosenMap = votingSystem.Choice2.label.SurfaceGui.TextLabel.Text

		else

			chosenMap = votingSystem.Choice3.label.SurfaceGui.TextLabel.Text

		end

		-- shows which map has won

		status.Value = "The Chosen map is: ".. chosenMap

		--- getting the map from the replicated storgae to the workspace

		for i, map in pairs(maps) do
			if chosenMap == map.Name then
				mapClone = map:Clone()
				mapClone.Parent = game.Workspace
			end
		end	

		--[[ another short delay right before the players get teleported you would also need to add 
		the same delay on the round system script]]
		wait(3)

		-- clears all the votes for next round

		for i, choice in pairs(choices) do
			choice.label.SurfaceGui.TextLabel.Text = " "
			choice.Image.SurfaceGui.ImageLabel.Image = " "
			choice.button.Votes:ClearAllChildren()
			rep.VoteReset:FireAllClients(choice.button)
		end

		-- this is if there are no teams wit dedicated spawns (free for all):

		--local spawns = mapClone.Spawns:GetChildren()

		local BlueTeamCount = {}
		local RedTeamCount = {}

		for i, plr in pairs(plrs:GetChildren()) do

			local char = plr.Character
			local humanRoot = char:WaitForChild("HumanoidRootPart")
			local nameGui = char.Head:FindFirstChild("NameGUI")

			local RedSpawns = mapClone.RedSpawns:GetChildren()
			local BlueSpawns = mapClone.BlueSpawns:GetChildren()

			-- picks a random spawn from each team
			local randomRedSpawn = RedSpawns[math.random(1,#RedSpawns)]
			local randomBlueSpawn = BlueSpawns[math.random(1,#BlueSpawns)]

			-- will put the current player into a team with the less amount of players

			if #RedTeamCount == 1 then

				plr.Team = blueTeam
				-- this is so we can make the spawn location for each player more randomized
				plr.CameraMode = "Classic"
				plr.CameraMaxZoomDistance = 9
				humanRoot.CFrame = randomBlueSpawn.CFrame + Vector3.new(math.random(1,3),math.random(1,3),math.random(1,3))

				table.insert(BlueTeamCount, plr.Name)
				if nameGui then
					nameGui.name.TextColor3 = blueTeamColor
				end
				print(plr.Name .. " put in ".. plr.Team.Name)

			elseif #RedTeamCount == 0 then

				plr.Team = redTeam
				plr.CameraMode = "LockFirstPerson"
				plr.CameraMaxZoomDistance = 0.5
				humanRoot.CFrame = randomRedSpawn.CFrame + Vector3.new(math.random(1,3),math.random(1,3),math.random(1,3))

				table.insert(RedTeamCount, plr.Name)

				if nameGui then
					nameGui.name.TextColor3 = redTeamColor
				end

				print(plr.Name .. " put in ".. plr.Team.Name)

				-- if both teams have the same amount of players, it choses a random team using math.random

			else

				local randTeam -- This just defines the variable

				while wait() do -- Every second (it won't be exact)
					randTeam = math.random(1, 2) -- Set the variable
				end

				if randTeam == 1 then

					plr.Team = blueTeam
					plr.CameraMode = "Classic"
					plr.CameraMaxZoomDistance = 9
					humanRoot.CFrame = randomBlueSpawn.CFrame + Vector3.new(math.random(1,3),math.random(1,3),math.random(1,3))

					table.insert(BlueTeamCount, plr.Name)

					if nameGui then
						nameGui.name.TextColor3 = blueTeamColor
					end

					print(plr.Name .. " put in ".. plr.Team.Name)

				else

					plr.Team = blueTeam
					plr.CameraMode = "Classic"
					plr.CameraMaxZoomDistance = 9
					humanRoot.CFrame = randomBlueSpawn.CFrame + Vector3.new(math.random(1,3),math.random(1,3),math.random(1,3))

					table.insert(RedTeamCount, plr.Name)
					if nameGui then
						nameGui.name.TextColor3 = redTeamColor
					end
					print(plr.Name .. " put in ".. plr.Team.Name)

				end
			end



			--------- if the player dies, it puts them back in the lobby and removes them from the team

			-- when a player has died
			char:WaitForChild("Humanoid").Died:Connect(function()

				plr.Team = lobbyTeam


			end)

		end	

	end	
end)
1 Like

				local randTeam -- This just defines the variable

				while wait() do -- Every second (it won't be exact)
					randTeam = math.random(1, 2) -- Set the variable
				end

				if randTeam == 1 then

What is this even supposed to do?
You don’t use a loop in such case, also since it’s infinite, the code after it won’t ever run.

It was originally local randTeam = math.Random(1,2)

I got a suggestion to change it to that

Remove the while wait() do
That’s why it’s not working.

Thats not the problem, it is working, its just not randomizing

It will never print after

	if randTeam == 1 then

Plus math.random() ranges between the values So basically like

math.random(30,50)

It will choose from 30-50 Not 30 or 50.

My script already works, its just not randomizing.

I want local randTeam = math.Random(1,2) to actually be random, it only randomizes one time and after that its the same. The script is not broken its perfectly fine

I’ll try to explain to you again
The problem is that it always choose 1 because math.random() ranges between values not choose from those 2 values
if you did math.random(1,2) it will always get 1 Because it chooses between the values not choose from those 2 values

math.random(25,50) -- Chooses from 25-30 (ex it chooses 30,35,40,45)

Then how do I fix the problem? Also it chooses 2 sometimes as well.

I’d like to point out you should never do

while wait() do

end

Since wait() should no longer be used, replace your loop with this:

while true do

   -- your code

   task.wait()
end
3 Likes

image
And here, instead of checking if it’s different than 1, check if its equal to 2.

What does that change? Also I am not used to task.wait() I haven’t scripted in a long time

math.random will include them math.random(1, 2) will return 1 or 2

I’m not 100% sure.

The loop is really unnecessary by the looks of things, why do you need the loop?

local randTeam  = math.random(1, 2) -- Set the variable

task.wait() is just the more optimized and more precise version of wait().

1 Like

I was kind of desperate to fix this issue, so it was originally local randTeam = math.random(1,2). Keep in mind that this actually worked but once someone was chosen a killer they would be killer until they leave, that is the issue. its not randomizing after the first random

thats what im trying to fix, sorry for being confusing

I still don’t quite understand, sorry.

All I want to say is that while () do will yeild your script until the criteria isn’t met anymore, meaning the script will pause running.

math.random(2) should work, picking a random number that is either 1 or 2.


You should try what the users in the thread have suggested if not already:

  • Change else to elseif randTeam == 2 then
  • Remove the loop and simply make it local randTeam = math.random(1, 2)

If neither of those work, I’m sorry but I don’t know how to help you.

You could just make it a function that returns a number instead?

local function randTeam(): number
    return math.random(1, 2)
end

if randTeam() == 1 then
else
end
if math.random(1, 2) == 1 then
else
end

The full call to math.random isn’t that long, I don’t see why making a whole function is necessary, especially when it takes more lines that just doing the code yourself.


Try putting a print("Done loop!") after the loop to make sure it’s actually moving on from it, because it shouldn’t be. I personally think you should look a little into while-loops.

while wait() do
    randTeam = math.random(1, 2)
end

print("Done loop!") --look for "Done loop!" in the output
1 Like

Wait() has its own benefits. Physics-based throttling, x2 update rate. More performant overall.

That’s simple logic. The random number plucked out by math.random (either 1 or 2) is stored in a variable. That variable will act as a constant. It will not change until manually changed again. If the initial assignment were to be 1, it wouldn’t change to anything else unless specifically reassigned.

Using a dynamic approach, simply writting math.random(1, 2) when you need to use it would guarantee a pseudo-random number between 1 and 2 each time the method is called