Sometimes, we need to create random behaviors that don't differ too much from a pivot point; this is the case of an aiming behavior. A normalized random behavior will shoot equally along the x and the y axes over a given distance from the aiming point. However, we would like most of the bullets to aim closer to the target because that's the expected behavior.
Most of the random functions out there return normalized values along the range given to them, and those are the expected results. Nonetheless, this is not completely useful for certain features in game development, as we just said. We will implement a random function to be used in our games with normal distribution instead of a normal distribution.
It is important to understand the differences between uniform and normal distribution. In the following figure, we can see a graphical representation of the behavior we're looking for by applying normal distribution with the example mentioned in the introductory text.
In the figure on the left-hand side, the uniform distribution spreads through the whole circle, and it is intended to be used in general random distributions. However, while developing other techniques, such as gun aiming, the desired random distribution will look more like the image on the right-hand side.
We will build a simple class as follows:
RandomGaussian
class:using UnityEngine; public class RandomGaussian { // next steps }
RangeAdditive
member function that initializes the necessary member variables:public static float RangeAdditive(params Vector2[] values) { float sum = 0f; int i; float min, max; // next steps }
if (values.Length == 0) { values = new Vector2[3]; for (i = 0; i < values.Length; i++) values[i] = new Vector2(0f, 1f); }
for (i = 0; i < values.Length; i++) { min = values[i].x; max = values[i].y; sum += Random.Range(min, max); }
return sum;
We should always strive for efficiency. That's why there's another way of delivering a similar result. In this case, we could implement a new member function based on the solution offered by Rabin and others (refer to the proceeding See also section):
public static ulong seed = 61829450; public static float Range() { double sum = 0; for (int i = 0; i < 3; i++) { ulong holdseed = seed; seed ^= seed << 13; seed ^= seed >> 17; seed ^= seed << 5; long r = (long)(holdseed * seed); sum += r * (1.0 / 0x7FFFFFFFFFFFFFFF); } return (float)sum; }