Random number the same everytime

Im trying to get a randomX and a randomZ value for placing something but it keeps returning the same thing

local randX = math.random(-75,75)
local randZ = math.random(-75,75)
local formula = region.CFrame + Vector3.new(randX,0,randZ)

everytime I run the game and i set the position of the thing i need to set when theres two or more it all puts them in the same location

2 Likes

because you’re using same variable so they will be same you can create another math.random() variable for formula2

But thats so redundant though is there any other workarounds?

edit : I only needed formula i was just testing if I did two if it would still give me the same random number

you can change this script to this:

function randX()
    local randomX = math.random(-75,75)
    return randomX
end

function randZ()
    local randomZ = math.random(-75,75)
    return randomZ
end

local formula = region.CFrame + Vector3.new(randX() , 0, randZ() )
local formula2 = region.CFrame + Vector3.new(randX() ,0 , randZ() )
print(formula)
print(formula2)

i guess?

edited code ^^^

That just might work let me try that

edit : @AtomTostcuOzgurUsta That didnt work I really thought it would

The numbers should be different; as far as I’m aware, without an explicit change to the seed, it should be different each generation per new session. Could only be applicable to the Random object.

Two ways to solve this are either to use math.randomseed(os.clock()) before generation or to use the Random object. Random will pull a seed itself, while math.randomseed will affect the seeding for math.random and take place globally (which is somewhat undesirable).

local RNG = Random.new()
local randX = RNG:NextInteger(-75, 75)
local randZ = RNG:NextInteger(-75, 75)
local formula = region.CFrame + Vector3.new(randX, 0, randZ)

On a separate note, is this calculation even valid? You’re adding a Vector3 to a CFrame. I would think that to make this valid you would either be using the Position of the CFrame or adding together two CFrames instead of two differing datatypes. Wondering if errors have ever appeared in the console for you.

There’s no reason to wrap this in a function. The underlying drawbacks from it, albeit trivial, aren’t appropriate to take - shouldn’t have to call a function and then return a value for something this simple.

1 Like

No errors have appeared in the console at all it just gives me back the same random number

edit : though i did change the seed though up at the top of the script

image

@lesserfantasy

If you don’t like the redundancy then take out the variables and incorporate the random function with the vector coordinates while applying the formula directly too so that it constantly gets a new randomized vector.

Example:

region.CFrame = region.CFrame + Vector3.new(math.random(-75, 75),0,math.random(-75,75))

I tried that also and it didnt work

Doesn’t work as in its not new random each time or do you mean it doesn’t change the CFrame?

You’re going to need to show more code then. If you’ve seeded and you get back the same position, then there’s a concern with the implementation you’re pursuing and not the randomness itself. As it is, it took me replying for you to include missing information critical to solving this problem which is the fact that you did seeding at all.

Im not change the regions cframe im changing a different object and also I have a function that takes in position / CFrame so I cant set the value like how you said befor

local plantsFolder = game.ServerStorage.plants:GetChildren()
local regionPart = game.Workspace:FindFirstChild("defaultMap").plantSpawns.plantSpawn1
local bottomLeft = regionPart.Position - (regionPart.Size / 2)
local topRight = regionPart.Position + (regionPart.Size / 2)
local region = Region3.new(bottomLeft,topRight)
local function spawnPlants(obj,pos)
	local newPlant = obj:Clone()
	newPlant.Parent = workspace
	newPlant.PrimaryPart:SetNetworkOwner(nil)
	newPlant:SetPrimaryPartCFrame(pos)
	print("Spawned "..newPlant.Name)
end
local randX = math.random(-75,75)
local randY = math.random(-75,75)
local formula = region.CFrame + Vector3.new(randX,0,randY)
spawnPlants(plantsFolder[math.random(1,#plantsFolder)],formula)
spawnPlants(plantsFolder[math.random(1,#plantsFolder)],formula)

@ArtFoundation I updated my reply

You really will have to show more code then, your only problem is not randomizing again if you’re doing multiple CFrame assignments.

In addition, we will not be able to find any other problems with the rest of the code if it’s not related to the original problem.

Oh, I get it. The problem makes far more sense now that code is supplied. Remember: you should always supply as much detail as possible when asking for support.

Your formula variable isn’t actually a formula. What you are doing there is evaluating an expression where a Vector3 is added as an offset for a CFrame and assigning that to the formula variable. This doesn’t change, so you’re effectively reusing the exact same position for all of your models when going out to place them in the map. You need to change your implementation up a bit.

If you ever only use that one region for your plants, then you can change the position method in the spawnPlants function. The position parameter can be kept as an override, otherwise it should use a random position as in when that function is called.

local function spawnPlants(obj,pos)
	local newPlant = obj:Clone()
	newPlant.Parent = workspace
	newPlant.PrimaryPart:SetNetworkOwner(nil)

	if pos then
		newPlant:SetPrimaryPartCFrame(pos)
	else
		local randX = math.random(-75,75)
		local randY = math.random(-75,75)
		local position = region.CFrame + Vector3.new(randX, 0, randY)
		newPlant:SetPrimaryPartCFrame(position)
	end

	print("Spawned "..newPlant.Name)
end

When calling spawnPlants, don’t pass a second argument. So for your bottom two calls:

spawnPlants(plantsFolder[math.random(1,#plantsFolder)])

Ideally you could resolve this in your initial code by using a new scope per spawnPlants call, but that wouldn’t solve your root misconception of how variable assignment works which is in fact not a formula, the contents on the right hand side get evaluated (“the equation is completed and the answer is returned, which gets assigned to the variable on the left hand side”). What that would have looked like:

for i = 1, 2 do
    local randX = math.random(-75,75)
    local randY = math.random(-75,75)
    local formula = region.CFrame + Vector3.new(randX,0,randY)
 
   spawnPlants(plantsFolder[math.random(1,#plantsFolder)],formula)
end

Makes the variables local to the current iteration and thus are not the same. Don’t use this though, use my advice as offered before this.

1 Like

I was really hoping that would work but its still spawning both of them in the same place for some reason

local function spawnPlants(obj,pos)
	local newPlant = obj:Clone()
	newPlant.Parent = workspace
	newPlant.PrimaryPart:SetNetworkOwner(nil)
	if pos then
		newPlant:SetPrimaryPartCFrame(pos)
	else
		local randX = math.random(-75,75)
		local randY = math.random(-75,75)
		local randomPosition = region.CFrame + Vector3.new(randX, 0, randY)
		newPlant:SetPrimaryPartCFrame(randomPosition)
	end
	print("Spawned "..newPlant.Name)
end

spawnPlants(plantsFolder[math.random(1,#plantsFolder)])
spawnPlants(plantsFolder[math.random(1,#plantsFolder)])

I made a spelling mistake in my code which I’ve corrected. Try it again. If it doesn’t work, I need to see your updated implementation as well - simply being told it doesn’t work isn’t sufficient enough for me to understand why you’re running into an issue that shouldn’t be.

1 Like

This is my updated code I copied it just as you did it all i did was change the position variable name

local function spawnPlants(obj,pos)
		local newPlant = obj:Clone()
		newPlant.Parent = workspace
		newPlant.PrimaryPart:SetNetworkOwner(nil)
		if pos then
			newPlant:SetPrimaryPartCFrame(pos)
		else
			local randX = math.random(-75,75)
			local randY = math.random(-75,75)
			local randomPosition = region.CFrame + Vector3.new(randX, 0, randY)
			newPlant:SetPrimaryPartCFrame(randomPosition)
		end
		print("Spawned "..newPlant.Name)
	end
	
	spawnPlants(plantsFolder[math.random(1,#plantsFolder)])
	spawnPlants(plantsFolder[math.random(1,#plantsFolder)])

@lesserfantasy you there?

For some reason I just had to add a wait to the new code I made and keep the randX and randZ variables inside of the scope of wherever im using it i guess

im guessing since when i was calling the function it was so fast that it gave the same set off random numbers at run time,which makes sense

for i = 1, #plantsFolder do
	local randX = math.random(-95,95)
	local randZ = math.random(-95,95)
	local forumla = region.CFrame + Vector3.new(randX,0,randZ)
	spawnPlants(plantsFolder[math.random(1,#plantsFolder)],forumla)
	wait(.35)
end

@lesserfantasy
@AtomTostcuOzgurUsta
@ArtFoundation

You don’t need to keep pinging, we’ll see the replies eventually. :stuck_out_tongue:

I went and created a repro file to test the code I was working with. Although the positions can get a little wild sometimes since it was just a rough recreation, the code wasn’t wrong, so I’m still not sure where anything went wrong. Waits don’t solve problems magically, so there’s an underlying problem there.

As expected, when I ran the code, the plants would position themselves differently per test.

PlantSpawnRepro.rbxl (91.7 KB)

1 Like

Well apparently in this case it did somehow because Im pretty sure I was just calling the functions at the same time too fast and it just assigned them all the same random X and Z

Thanks for everything though