Keeping random numbers consistant

I am trying to make a world generate based on a seed how ever i am struggling to keep it the same based on the seed yet still random.

I am trying to make every chunk have its own random number based on the seed.
e.g. Vector3.new(-5,0,5) will always have a random number between -180 and 180 on seed 1

for now i am just testing with these chunks with the following code how ever its not very random as i can spot some very obvious patterns.

local s = seed

for _,chunk in game.Workspace.Chunks:GetChildren() do
	local x = chunk.Position.X
	local z = chunk.Position.Z
	
	math.randomseed(s) s = math.random(-180,180)
	
	chunk.Orientation = Vector3.new(0,math.random(-360,360),0)
end

Im sure the solution is really simple and im just stupid or maybe its been solved before but i did some searching and couldnt find any help.

you can try this:

local RNG = require(script.RNG)
local Seed = Random.new():NextInteger(-180, 180)

for ID , chunk in game.Workspace.Chunks:GetChildren() do
	local x = chunk.Position.X
	local z = chunk.Position.Z

	local Y = RNG.new(Seed .. ID .. "ChunkOrientationRNG"):NextNumber(-360, 360)

	chunk.Orientation = Vector3.new(0,Y,0)
	
end

RNG module:

--[VARIABLES]

local Min = -2147483648
local Max = 2147483647
local Range = Max - Min

--[MODULE]

local RNG = {}

RNG.WrapNumber = function (Number)
	
	local Result = (Number - Min) % Range + Min
	
	if Result > Max then
		
		Result = Result - Range
		
	end
	
	return Result
	
end

RNG.HashString = function (String : string)
	
	local Hash = 2166136261
	
	for Index = 1, #String do
		
		Hash = bit32.bxor(Hash, string.byte(String, Index)) * 16777619 
		Hash = RNG.WrapNumber(Hash)
		
	end
	
	return Hash
	
end

RNG.new = function (Seeds : Seeds)
	
	return Random.new(RNG.HashString(Seeds))
	
end

return RNG
1 Like

why are you changing seed after each random call?

i tried to make the random number consistant after each call based on the starting seed but it doesnt work cause it results in a pattern

Ill try this and lyk but tysm for the rng module anyway i was struggling with my own :sob:

1 Like

no problem! you can add more parameters but i think thats enough

1 Like

kinda get what you want, random will be consistent on same seed as long as you generate your objects in consistent order, the problem is :GetChildren() returns blocks in random order
and btw use Random object if you want seeded random

1 Like

Thank you i will. also your code seems to work im just worried if there is a pattern at all but i cant tell.

also my origonal plan around thr get children being random is to use the X and Z values to influence the random number

are you talking about my code? and if so, you can add more parameters in the RNG.new

oh shoot yeah im replying to the wrong people thank you for the help :sob:

1 Like

its not really the parameters that im worried about, its the fact that some of these numbers are fairly similar like how 4 numbers in the middle are close to 80 or 90 and the other 4 in the middle seem to be close to -150

i know, but adding more parameters can make it more random and reduce the pattern

1 Like

Each chunk’s seed is derived from the previous chunk’s result instead of its own position, making the output order-dependent and pattern-prone. You have just hit maths little secret, there is no truly real random..

local s = seed

for _, chunk in game.Workspace.Chunks:GetChildren() do
    local x = chunk.Position.X
    local z = chunk.Position.Z

    math.randomseed(s + x * 73856093 + z * 19349663)

    chunk.Orientation = Vector3.new(0, math.random(-180, 180), 0)
end
2 Likes

that would explain a lot with this method and i kind of realised that :sob:.
is there any other way around this such as using a different formula or some kind of randomness map based on a seed?

Depending on how deep you want to go, you may want to look into Perlin Noise. But that is a different topic entirely. You should be fine with that last post. The prime multiplier spatial hash gives every chunk a unique deterministic seed based solely on its position and the world seed.

1 Like

that prime multiplier spatial hash thing sounds exactly like what im looking for. ill look into it

looking at what 2112Jay said in post Keeping random numbers consistant - #13 by 2112Jay

he is right and even though the prime multiplier spatial hash seems a good alternative in the end all i can do with a pseudorandom algorithm is make the patterns less obvious. i ended up settling with this code i made my self.

local seed = 23987561
local s = seed

local grid_szie = 16
local step = 2

for x = -grid_szie / 2,grid_szie / 2,step do
	for z = -grid_szie / 2,grid_szie / 2,step do
		
		local chunk for _,c in game.Workspace:GetPartBoundsInBox(CFrame.new(Vector3.new(x,0,z)),Vector3.one) do
			if c.Parent == game.Workspace.Chunks then chunk = c break end
		end if not chunk then warn("no chunk found at",x,z) continue end
		
		s = Random.new(s):NextNumber(-180,180) print(s)
		
		chunk.Orientation = Vector3.new(0,math.floor(s),0)
		
	end
end 

which results in this:

im not completely happy with it but works just fine for what im doing. players arent to notice anyway. thank you all for your help this question was a little silly.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.