I tried doing this, by doing string.random (which assuming is not even close to the answer, or something that even exists), then I wanted to see if string variables would work with math.random, but they didn't.
So how exactly do I do other random stuff besides math.random?
The only random functionality Lua provides is math.random
. It does three things:
math.random()
--> 0.58201314802
math.random(5)
--> 4
math.random(17, 20)
--> 18
Remember that at a fundamental level, everything on the computer is just numbers, so this shouldn't be too discouraging. If we have random numbers, we should be able to get random anything.
Let's say you want a random number x
between low
and high
. Then we can write x
as low + m
where m
is between 0
and high - low
.
As a result, we can generate x
as
x = low + (high - low) * math.random()
This is uniformly between low
and high
(including decimal numbers).
You can use the same math to generate points randomly between two Vector3s.
For the types that have a :Lerp
method like Color3, Vector3, and CFrame, you can also take advantage of math.random()
in a similar way:
x = low:lerp(high, math.random())
For instance, let's say we want to pick a random thing from a list:
flavors = {"chocolate", "vanilla", "strawberry"}
We can only pick random numbers, so what exactly is numbered about this list? There's an obvious thing: the keys. flavors[1]
is "chocolate"
while flavors[3]
is "strawberry"
.
That means if we can pick a random number of 1
, 2
, and 3
, we can turn that into a random element of flavors
.
In general, to choose a random element from list
, you can use
randomElement = list[ math.random(#list) ] -- math.random(#list) is a random index of list... thus -- the thing at that position-- `list [ __ ]` --is a random element of list
This is the fundamental way that everything is done. Figure it out in terms of numbers!
One way you can get "random positions" is when you're doing something like picking a random spawn location. In that case, you would probably actually use picking a random thing from a list.
Other times, you want to pick a random point in a particular region.
A parallelogram (e.g., rectangle) can be defined in terms of a corner and its two sides as vectors.
For instance
start = Vector3.new(0, 20, 0) right = Vector3.new(10, 0, 0) up = Vector3.new(0, 30, 0) -- Axis-Aligned Rectangle from (0, 20, 0) to (0, 20, 0) + (10, 0, 0) + (0, 30, 0) = (10, 50, 0)
we can generate a random point inside pretty easily:
local u = math.random() local v = math.random() local point = start + right * u + up * v
Often, these rectangles will be ones parallel to the XZ plane. This makes the above form in a way simpler:
wide = Vector3.new(1, 0, 0) * width -- or Vector3.new(width, 0, 0) tall = Vector3.new(0, 0, 1) * height -- or Vector3.new(0, 0, height) local point = start + wide * math.random() + tall * math.random() -- This would be the same as local point = start + Vector3.new(math.random() * width, 0, 0) + Vector3.new(0, 0, math.random() * height) -- which is the same as local point = start + Vector3.new( math.random() * width, 0, math.random() * height )
Often I see code that looks like this:
pos = Vector3.new( math.random(-50, 200), 0, math.random(-30, 100) )
I would consider this to be wrong, usually, because it will only generate them to the nearest integer. You should use the full range of numbers, like in the above:
pos = Vector3.new( -50 + math.random() * 250, 0, -30 + math.random() * 130 )
At first, it would seem that generating a random point inside of a sphere would not be very different.
Here's a simple (bad) solution:
-- returns a random vector in the cube ranging from -- [-1, 1] for x, y, z function randomCube() return Vector3.new( math.random() * 2 - 1, math.random() * 2 - 1, math.random() * 2 - 1) end function randomSphere() local cube = randomCube() if cube.magnitude > 1 then return cube.unit else return cube end end
The idea is that we just "clamp" the points outside of the unit sphere to the surface. While this will generate random points and they will all be in a sphere, they won't be uniform. Since there's a lot of space outside of the sphere near the corners of the cube, there will be 6 points on this "sphere" that are much more common than the other points.
That would mean if we used the above (or for that matter, simply randomCube
) for inaccuracy in a game, you would have a different amount of inaccuracy when firing diagonally as opposed to horizontally.
What's the solution? There aren't overly nice ones. (You can search for them online). A simple (but very slow) option is to just repeat until you get something inside the sphere:
function randomSphere() while true do local c = randomCube() if c.magnitude < 1 then return c end end end
See also Sphere Point Picking on MathWorld for another way to do it (and also why using polar coordinates isn't a solution)
If there's another specific thing you want to ask about, comment on it and I will write a portion on it.