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

때로는 항목을 임의로 선택하면서 일부 항목이 선택될 확률이 다른 항목보다 더 높아지도록 해야 합니다. 예를 들어 NPC는 플레이어를 만날 때 몇 가지 다른 방법으로 반응할 수 있습니다.

  • 친근하게 맞이할 확률 50%
  • 도망갈 확률 25%
  • 즉시 공격할 확률 20%
  • 돈을 선물로 제안할 확률 5%

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])`

줄을 더 작거나 같음 테스트로 변경하면 추가 return 문이 방지되지만 확률이 영(0)인 항목이 간헐적으로 선택될 수 있습니다.

Weighting continuous random values

플로트 배열 메서드는 불연속적인 결과가 있는 경우 효과적이지만, 상황에 따라 더 연속적인 결과를 만들고 싶을 수도 있습니다. 예를 들어 보물 상자에서 찾은 금화의 개수를 랜덤화하고 이 개수가 1과 100사이의 임의 수가 되도록 하되, 더 낮은 수가 될 확률이 더 높아지도록 하고 싶을 수 있습니다. 플로트 배열 메서드를 사용하여 이렇게 하려면 플로트 구간(긴 종이 조각의 각 부분)이 100개인 거대한 배열을 설정해야 합니다. 자연수로 제한하지 않고 범위에 속한 아무 숫자나 얻고 싶으면 이 방법을 사용할 수 없습니다.

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.

선형 곡선은 값에 가중치를 전혀 부여하지 않습니다. 곡선의 각 점에서 수평 좌표와 수직 좌표가 같습니다.
선형 곡선은 값에 가중치를 전혀 부여하지 않습니다. 곡선의 각 점에서 수평 좌표와 수직 좌표가 같습니다.
이 곡선의 앞 부분은 완만하지만 끝으로 갈수록 가파르므로 작은 값을 얻을 확률이 더 높고 큰 값을 얻을 확률이 감소합니다. 곡선에서 x=0.5인 점의 높이는 약 0.25이므로, 0과 0.25 사이의 값을 얻을 확률이 50%입니다.
이 곡선의 앞 부분은 완만하지만 끝으로 갈수록 가파르므로 작은 값을 얻을 확률이 더 높고 큰 값을 얻을 확률이 감소합니다. 곡선에서 x=0.5인 점의 높이는 약 0.25이므로, 0과 0.25 사이의 값을 얻을 확률이 50%입니다.
이 곡선은 처음과 끝 부분이 모두 완만하므로 양 극단에 가까운 값이 더 많고, 가운데 부분은 가파르므로 이 부분에는 값이 상대적으로 적습니다. 또한 이 곡선에서는 높이 값이 전반적으로 위로 올라가 있습니다. 곡선의 하한이 1이고 곡선의 상한이 10이므로, 곡선에서 생성되는 값의 범위는 앞의 곡선처럼 01이 아니라 110입니다.
이 곡선은 처음과 끝 부분이 모두 완만하므로 양 극단에 가까운 값이 더 많고, 가운데 부분은 가파르므로 이 부분에는 값이 상대적으로 적습니다. 또한 이 곡선에서는 높이 값이 전반적으로 위로 올라가 있습니다. 곡선의 하한이 1이고 곡선의 상한이 10이므로, 곡선에서 생성되는 값의 범위는 앞의 곡선처럼 01이 아니라 110입니다.

위의 곡선은 확률 이론 가이드에서 볼 수 있는 확률 분포 곡선이 아니라 역누적 확률 곡선에 더 가깝습니다.

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

많이 사용되는 게임 기법 중 하나로, 알려진 아이템 집합에서 선택하되 아이템이 무작위순으로 도착하게 하는 방법이 있습니다. 예를 들어 포커 카드는 일반적으로 예측하기 쉬운 순서로 뽑히지 않도록 잘 섞어야 합니다. 각 요소를 배열의 임의 인덱스에 있는 다른 요소와 맞바꿔서 배열의 아이템 순서를 섞을 수 있습니다.

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

일반적인 작업 중 하나로, 여러 아이템을 집합에서 무작위로 선택하되 같은 아이템이 두 번 이상 선택되지 않도록 할 수 있습니다. 예를 들어 임의의 스폰 포인트에서 여러 NPC를 생성하되 각 포인트에서 NPC가 하나만 생성되도록 하고 싶을 수 있습니다. 이렇게 하려면 각 아이템을 선택된 집합에 추가할지 여부를 임의로 결정하는 작업을 모든 아이템에 대해 차례로 반복하여 수행합니다. 각 아이템의 차례가 될 때 해당 아이템이 선택될 확률은 필요한 아이템 수를 선택 가능한 나머지 아이템 수로 나눈 값과 같습니다.

예를 들어 사용 가능한 스폰 포인트가 10개 있지만 다섯 개만 선택해야 하는 경우, 첫 번째 아이템이 선택될 확률은 5/10, 즉 0.5입니다. 이 아이템이 선택되면 두 번째 아이템이 선택될 확률은 4/9인 0.44입니다. 아이템이 4개 필요하고 선택할 수 있는 아이템이 9개 남아 있기 때문입니다. 하지만 첫 번째 아이템이 선택되지 않은 경우 두 번째 아이템이 선택될 확률은 5/9, 즉 0.56입니다. 여전히 다섯 개가 필요하고 선택할 수 있는 아이템이 9개 남아 있기 때문입니다. 집합에 필요한 다섯 개 아이템이 포함될 때까지 이 과정을 계속 반복합니다. 이렇게 하기 위한 코드는 다음과 같습니다.

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

선택은 무작위지만, 선택된 집합의 아이템 순서는 오리지널 배열 순서와 동일합니다. 아이템을 한 번에 하나씩 차례대로 사용하려는 경우 순서에 따라 아이템을 부분적으로 예측할 수 있으므로 사용 전에 배열 순서를 섞어야 할 수 있습니다.

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);`

그러면 변의 길이가 1단위인 큐브 안에 있는 포인트가 얻어집니다. 간단히 벡터의 X, Y 및 Z 컴포넌트를 원하는 변의 길이로 곱해 큐브를 스케일할 수 있습니다. 축 하나를 0으로 설정하면 포인트가 항상 단일 평면 안에 있게 됩니다. 예를 들어 “그라운드”에서 랜덤 포인트를 선택하려면 일반적으로 X 및 Z 컴포넌트를 임의로 설정하고 Y 컴포넌트를 0으로 설정합니다.

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