Version: 2021.1
Important Classes - Mathf
Important Classes - Debug

Important Classes - Random

The Random class provides you with easy ways of generating various commonly required types of random values.

This page provides an overview of the Random class and its common uses when scripting with it. For an exhaustive reference of every member of the Random class and further technical details about it, see the Random script reference.

Follow the links below for further details and examples of these useful methods.

Simple random numbers

Random.value gives you a random floating point number between 0.0 and 1.0. A common usage is to convert it to a number between zero and a range of your choosing by multiplying the result.

Random.Range gives you a random number between a minimum and maximum value that you provide. It returns either an integer or a float, depending on whether the min and max values provided are integers or floats.

Random points within Circles or Spheres

Random.insideUnitCircle returns a randomly selected point inside a circle with a radius of 1 (Again you can multiply the result to get a random point within a circle of any size).

Random.insideUnitSphere returns a randomly selected point inside a sphere with a radius of 1.

Random.onUnitSphere returns a randomly selected point on the surface of a sphere with a radius of 1.

Other types of random values

Unity’s random class also offers a few other types of random value.

To generate a random rotation, use Random-rotation.

To generate a random color, use Random.ColorHSV.

Choosing a Random Item from an Array

Picking an array element at random boils down to choosing a random integer between zero and the array’s maximum index value (which is equal to the length of the array minus one). This is easily done using the built-in Random.Range function:-

 `var element = myArray[Random.Range(0, myArray.Length)];``

Note that Random.Range returns a value from a range that includes the first parameter but excludes the second, so using myArray.Length here gives the correct result.

Choosing Items with Different Probabilities

Algunas veces, usted necesita escoger elementos aleatoriamente pero con algunos elementos con mayor probabilidad de ser escogidos que otros. Por ejemplo, un NPC puede reaccionar de maneras distintas cuando se encuentra un jugador.

  • 50% de probabilidad de un saludo amistoso
  • 25% de probabilidad de huir
  • 20% de probabilidad de un ataque inmediato
  • 5% de probabilidad de ofrecer dinero como un regalo

You can visualize these different outcomes as a paper strip divided into sections each of which occupies a fraction of the strip’s total length. The fraction occupied is equal to the probability of that outcome being chosen. Making the choice is equivalent to picking a random point along the strip’s length (say by throwing a dart) and then seeing which section it is in.

In the script, the paper strip is actually an array of floats that contain the different probabilities for the items in order. The random point is obtained by multiplying Random.value by the total of all the floats in the array (they need not add up to 1; the significant thing is the relative size of the different values). To find which array element the point is “in”, firstly check to see if it is less than the value in the first element. If so, then the first element is the one selected. Otherwise, subtract the first element’s value from the point value and compare that to the second element and so on until the correct element is found. In code, this would look something like the following:-

float Choose (float[] probs) {

    float total = 0;

    foreach (float elem in probs) {
        total += elem;
    }

    float randomPoint = Random.value * total;

    for (int i= 0; i < probs.Length; i++) {
        if (randomPoint < probs[i]) {
            return i;
        }
        else {
            randomPoint -= probs[i];
        }
    }
    return probs.Length - 1;
}

Note that the final return statement is necessary because Random.value can return a result of 1. In this case, the search will not find the random point anywhere. Changing the line

 `if (randomPoint < probs[i])`

… a una prueba de menos que-o-igual que, evitaría la instrucción return extra, pero también permitiría un elemento ser elegido ocasionalmente, incluso cuando su probabilidad es cero.

Weighting continuous random values

El método de arreglo de floats funciona bien si usted tiene resultados discretos, pero también hay situaciones dónde usted quiere producir un resultado más continuo - digamos, usted quiere volver aleatorio la cantidad de piezas de oro que se pueden encontrar en un cofre, y usted lo quiere hacer que sea un número entre 1 y 100, pero quisiera hacer que sea más probable obtener un número menor. Utilizando el método de arreglo de floats esto requiere que usted configure un arreglo de 100 floats (i.e. secciones en una tira de un papel) lo cual es difícil de manejar; y si usted no está limitado a números enteros pero cualquier cualquier número entre ese rango, es imposible utilizar ese acercamiento.

A better approach for continuous results is to use an AnimationCurve to transform a ‘raw’ random value into a ‘weighted’ one; by drawing different curve shapes, you can produce different weightings. The code is also simpler to write:

float CurveWeightedRandom(AnimationCurve curve) {
    return curve.Evaluate(Random.value);
}

A ‘raw’ random value between 0 and 1 is chosen by reading from Random.value. It is then passed to curve.Evaluate(), which treats it as a horizontal coordinate, and returns the corresponding vertical coordinate of the curve at that horizontal position. Shallow parts of the curve have a greater chance of being picked, while steeper parts have a lower chance of being picked.

Una curva lineal no pondera valores en absoluto; la coordenada horizontal es igual a la coordenada vertical para cada punto en la curva.
Una curva lineal no pondera valores en absoluto; la coordenada horizontal es igual a la coordenada vertical para cada punto en la curva.
Esta curva es menos profunda al principio, y luego más empinado al final, por lo que tiene una mayor probabilidad de valores más bajos y una probabilidad reducida de valores mayores. Usted puede ver que la altura de la curva en la linea dónde x=0.5 es acerca de 0.25, lo cual significa que tiene una probabilidad mayor a la mitad de obtener un valor entre 0 y 0.25.
Esta curva es menos profunda al principio, y luego más empinado al final, por lo que tiene una mayor probabilidad de valores más bajos y una probabilidad reducida de valores mayores. Usted puede ver que la altura de la curva en la linea dónde x=0.5 es acerca de 0.25, lo cual significa que tiene una probabilidad mayor a la mitad de obtener un valor entre 0 y 0.25.
Esta curva es menos profunda al principio y al final, haciendo que los valores cercanos a los extremos sea más común, y en la mitad pendiente lo cual haría esos valores muy raros. Tenga en cuenta que con esta curva, los valores de altura han aumentado para arriba: el final de la curva está en 1, y la parte superior de la curva está en 10, lo cual significa que los valores producidos por la curva estarán en el rango de 1-10, en vez de 0-1 como las curvas anteriores.
Esta curva es menos profunda al principio y al final, haciendo que los valores cercanos a los extremos sea más común, y en la mitad pendiente lo cual haría esos valores muy raros. Tenga en cuenta que con esta curva, los valores de altura han aumentado para arriba: el final de la curva está en 1, y la parte superior de la curva está en 10, lo cual significa que los valores producidos por la curva estarán en el rango de 1–10, en vez de 0–1 como las curvas anteriores.

Tenga en cuenta que estas curvas no son curvas distribuidas con probabilidad como las que usted encontraría en una guía de teoría de probabilidad, pero son más como curvas de probabilidad inversamente acumulativas.

By defining a public AnimationCurve variable on one of your scripts, you will be able to see and edit the curve through the Inspector window visually, instead of needing to calculate values.

This technique produces floating-point numbers. If you want to calculate an integer result - for example, you want 82 gold pieces, rather than 82.1214 gold pieces - you can just pass the calculated value to a function like Mathf.RoundToInt().

Shuffling a List

Una mecánica de juego común es elegir un conjunto conocido de artículos, pero que ellos lleguen en un orden aleatorio. Por ejemplo, una baraja de cartas se barajan normalmente para que no salgan en una secuencia predecible. Usted puede barajar los elementos de una matriz, visitando cada elemento e intercambiándolos con otro elemento situado en un índice al azar de la matriz:-

void Shuffle (int[] deck) {
    for (int i = 0; i < deck.Length; i++) {
        int temp = deck[i];
        int randomIndex = Random.Range(0, deck.Length);
        deck[i] = deck[randomIndex];
        deck[randomIndex] = temp;
    }
}

Choosing from a Set of Items Without Repetition

Una tarea común es elegir un número de elementos al azar de un conjunto sin coger el mismo más de una vez. Por ejemplo, usted podrá querer generar un número de NPCs en puntos de regeneración al azar, pero asegurarse de que sólo un NPC se genera en cada punto. Esto se puede hacer mediante la iteración a través de los elementos en la secuencia, tomando una decisión al azar para cada uno sobre si es o no, agregado al conjunto elegido. A medida que cada elemento es visitado, la probabilidad de ser elegido es igual al número de elementos que se necesita todavía, dividido por el número que aún queda para ser escogidos.

Como un ejemplo, supongamos que hay diez puntos de regeneración disponibles, pero sólo cinco deben ser usados. La probabilidad de que el primer punto sea elegido es de 5 / 10 o 0.5. Si es elegido, entonces la probabilidad para el segundo elemento será de 4 / 9 o 0.44 (ie, cuatro elementos todavía faltan, nueve restantes para elegir). Esto continúa hasta que el conjunto contenga los cinco elementos requeridos. Usted puede logar esto en código de la siguiente manera:-

Transform[] spawnPoints;

Transform[] ChooseSet (int numRequired) {
    Transform[] result = new Transform[numRequired];

    int numToChoose = numRequired;

    for (int numLeft = spawnPoints.Length; numLeft > 0; numLeft--) {

        float prob = (float)numToChoose/(float)numLeft;

        if (Random.value <= prob) {
            numToChoose--;
            result[numToChoose] = spawnPoints[numLeft - 1];

            if (numToChoose == 0) {
                break;
            }
        }
    }
    return result;
}

Tenga en cuenta que aunque la selección es al azar, los elementos en el conjunto elegido estarán en el mismo orden que tenían en la matriz original. Si los elementos se van a utilizar de uno en uno en secuencia entonces el orden puede hacer que en parte sean predecibles, por lo que puede ser necesario barajar la matriz antes de su uso.

Random Points in Space

A random point in a cubic volume can be chosen by setting each component of a Vector3 to a value returned by Random.value:-

` var randVec = Vector3(Random.value, Random.value, Random.value);`

Esto le da un punto dentro el cubo con lados de una unidad. El cubo puede ser escalado simplemente multiplicando los components X, Y y Z del vector por el tamaño del lado deseado. Si alguno de estos ejes es establecido a cero, el punto siempre estará dentro un plano único. Por ejemplo, escogiendo un punto aleatorio en el “piso” es usualmente una cuestión de ajustar los components X y Z aleatoriamente y ajustar el component Y a cero.

When the volume is a sphere (ie, when you want a random point within a given radius from a point of origin), you can use Random.insideUnitSphere multiplied by the desired radius:-

` var randWithinRadius = Random.insideUnitSphere * radius;`

Note that if you set one of the resulting vector’s components to zero, you will not get a correct random point within a circle. Although the point is indeed random and lies within the right radius, the probability is heavily biased toward the edge of the circle and so points will be spread very unevenly. You should use Random.insideUnitCircle for this task instead:-

 `var randWithinCircle = Random.insideUnitCircle * radius;`
Important Classes - Mathf
Important Classes - Debug
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961