Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How to use math.noise?

Asked by
Kyokamii 133
9 years ago

I really don't understand how it works, and I didnt find a ROBLOX tutorial. So, my final guess was to come here: Can somebody tell me how to use math.noise function in ROBLOX? Note that i'd like to create a random map.

0
What do you want to accomplish? RepeatLua 90 — 9y
0
I'd like to create a randomised map. Kyokamii 133 — 9y
1
Why not use math.random()? M39a9am3R 3210 — 9y
0
Because Perlin Noise is the basic stuff to use for generated stuff. Kyokamii 133 — 9y
0
No, actually because Perlin noises is a smoother random. greatneil80 2647 — 5y

1 answer

Log in to vote
13
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

math.noise solve three important problems that makes it good for procedurally generated stuff:

  • aperiodic -- the result is not predictable
  • smooth -- the result is never sharp (and neither are its derivatives)
  • multidimensional -- the result works well in more than one dimension (up to three)

First, ignoring the fact that math.noise is multidimensional; imagine we want to make a hilly side-scrolling platformy game.

Then we can visualize this with code like the following:

for i = 1, 15 do
    print( string.rep("#", math.random(10, 20) ) )
end
###################
####################
###########
##############
###########
####################
##############
############
##################
############
##################
##################
####################
###################
##############

That's definitely unpredictable, but it's not smooth like the real world.

Another option would be use to something like math.sin:

for i = 1, 15 do
    print( string.rep("#", 10 + 5 * math.sin(i) ) )
end
##############
###############
###########
######
#####
#########
#############
###############
############
#######
#####
#######
############
###############
#############

While this is smooth, it's obviously repeating itself, and that will look worse and worse the more of it you seen.

We can sort of solve this problem by adding two different sin waves together:

#############
##############
############
##########
##########
############
##############
##############
############
#########
#######
#######
#########
##########
#########
#######
######
#######
##########
############
#############
############
##########
##########
############
##############
##############
############
#########
#######
########
##########
##########
#########
######
#####
#######
##########
############
############
###########
##########
##########
#############
###############

However you can still see the repetition in the pattern.

THE SOLUTION: math.noise

Basically, all we have to do is replace math.sin with math.noise and you get what you want.

There are a few important considerations:

  • math.noise is bounded between -0.5 and 0.5**
  • if x and y differ by more than 1, then math.noise(x) and math.noise(y) are completely unrelated. That means when you sample from math.noise you have to sample closer than 1 together.
for i = 1, 45 do
    print( string.rep("#", 10 + 10 * math.noise(i / 5)  ) )
end
###########
###########
#########
#########
##########
############
###############
###############
############
##########
#########
#########
###########
###########
##########
########
#######
########
##########
##########
##########
########
#######
########
##########
############
###############
###############
############
##########
########
#####
#####
########
##########
############
###############
###############
############
##########
########
#######
########
##########
##########

Multidimensional

The other nice thing is that you can use math.noise(x, y, z).

For example, if you're generating terrain, you can get an interesting, random, smooth height at position (x, math.noise(x / 10, z / 10), z).

For example,

for x = 1, 100 do
    for z = 1, 100 do
        local height = (math.noise(x / 20, z / 20) + 2) * 50
        local p = Instance.new("Part", workspace)
        p.Locked, p.Anchored = true, true
        p.Size = Vector3.new(4, height, 4)
        p.CFrame = CFrame.new(4 * x, height / 2, 4 * z)
        wait()
    end
end

Gotchas

math.noise isn't perfect. It has a few problems:

For any integer i, math.noise(i) is zero. That means there is a periodic occurrence of 0 in any result from math.noise.

You can cover this up by using two math.noise which have an irrational relative frequency; for example,

math.noise( f * i )

-- (replace with)

math.noise( f / math.sqrt(2) * i ) + math.noise( f * math.sqrt(2) * i )

Though this will have the effect of amplifying another problem with math.noise; math.noise likes to give very small values.


math.noise also appears to have some precision problems when you use relatively large numbers; try to stick fewer than a few thousand.

1
Wow! You basically wrote a wiki article! Someone make this guy a wiki editor! nilVector 812 — 9y
0
He already is, actually. adark 5487 — 9y
0
Great explanation; I was kind of curious as to what math.noise was used for myself. Glad to see there's such a useful tool for terrain generation. Legojoker 345 — 9y
0
Thanks a lot, BlueTaslem. Kyokamii 133 — 9y
Ad

Answer this question