Handling random numbers better

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.

Getting ready

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.

Getting ready

How to do it…

We will build a simple class as follows:

  1. Create the RandomGaussian class:
    using UnityEngine;
    
    public class RandomGaussian
    {
        // next steps
    }
  2. Define the 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
    }
  3. Check whether the number of parameters equals zero. If so, create three new values:
    if (values.Length == 0)
    {
        values = new Vector2[3];
        for (i = 0; i < values.Length; i++)
            values[i] = new Vector2(0f, 1f);
    }
  4. Sum all the values:
    for (i = 0; i < values.Length; i++)
    {
        min = values[i].x;
        max = values[i].y;
        sum += Random.Range(min, max);
    }
  5. Return the resulting random number:
    return sum;

There's more…

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;
}

See also

  • For further information on the theory behind the Gaussian random generator and other advanced generators, please refer to the book Game AI Pro by Steve Rabin, article number 3
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset