Мои Уведомления
Привет, !
Мой Аккаунт Мои Финансы Мои Подписки Мои Настройки Выход
Руководство API скрипты

Класс Random предоставляет простые способы создания различных часто используемых типов случайных значений.

На этой странице представлен обзор класса Random и его частого использования при написании сценариев. Исчерпывающую информацию о каждом члене класса Random и дополнительную техническую информацию о нем см. в справочнике по скрипту Random.

Следуйте приведенным ниже ссылкам для получения дополнительной информации и примеров этих полезных методов.

Простые случайные числа

Random.value дает вам случайное число с плавающей запятой между 0,0 и 1,0. Обычно его используют для преобразования в число от нуля до диапазона по вашему выбору путем умножения результата.

Random.Range дает вам случайное число между минимумом и максимумом значение, которое вы предоставляете. Он возвращает либо целое число, либо число с плавающей запятой, в зависимости от того, являются ли предоставленные минимальные и максимальные значения целыми числами или числами с плавающей запятой.

Случайные точки внутри кругов или сфер

Random.insideUnitCircle возвращает случайно выбранную точку внутри круга с радиусом 1 (опять же, вы можете умножить результат, чтобы получить случайную точку внутри круга любого размера).

Random.insideUnitSphere возвращает случайно выбранную точку внутри сферы с радиусом 1.

Random.onUnitSphere возвращает случайно выбранную точку на поверхность сферы радиусом 1.

Другие типы случайных значений

Класс случайных чисел Unity также предлагает несколько других типов случайных значений.

Чтобы сгенерировать случайный поворот, используйте Random.rotation.

Чтобы сгенерировать случайный цвет, используйте Random.ColorHSV.

Выбор случайного элемента из массива

Случайный выбор элемента массива сводится к выбору случайного целого числа между нулем и максимальным значением индекса массива (которое равно длине массива минус единица). Это легко сделать с помощью встроенной функции Random.Range:-

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

Обратите внимание, что Random.Range возвращает значение из диапазона, который включает первый параметр, но исключает второй, поэтому использование myArray.Length дает правильный результат.

Выбор элементов с разной вероятностью

Иногда вам нужно выбрать элементы случайным образом, но некоторые элементы будут выбраны с большей вероятностью, чем другие. Например, NPC может реагировать по-разному, когда сталкивается с игроком:-

  • 50% шанс дружеского приветствия
  • 25% шанс убежать
  • Вероятность немедленной атаки 20%
  • 5%-й шанс предложить деньги в качестве подарка

Вы можете визуализировать эти разные результаты в виде полоски бумаги, разделенной на секции, каждая из которых занимает часть общей длины полоски. Занятая доля равна вероятности того, что будет выбран этот исход. Выполнение выбора эквивалентно выбору случайной точки вдоль полосы (скажем, броском дротика) и последующему просмотру, в какой секции она находится.

В скрипте бумажная полоска на самом деле представляет собой массив чисел с плавающей запятой, которые содержат различные вероятности для элементов по порядку. Случайная точка получается путем умножения Random.value на сумму всех чисел с плавающей запятой в массиве (их сумма не обязательно должна равняться 1; важным моментом является относительный размер разные значения). Чтобы определить, в каком элементе массива находится точка, сначала проверьте, не меньше ли оно значения в первом элементе. Если это так, то выбран первый элемент. В противном случае вычтите значение первого элемента из значения точки и сравните его со вторым элементом и так далее, пока не будет найден правильный элемент. В коде это будет выглядеть примерно так:-

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

Обратите внимание, что окончательный оператор return необходим, поскольку Random.value может возвращать результат 1. В этом случае поиск нигде не найдет случайную точку. Изменение строки

`if (randomPoint < probs[i])`

…в тесте "меньше или равно" можно избежать дополнительного оператора возврата, но также позволит время от времени выбирать элемент, даже если его вероятность равна нулю.

Взвешивание непрерывных случайных значений

Метод массива с плавающей запятой хорошо работает, если у вас есть дискретные результаты, но также бывают ситуации, когда вы хотите получить более непрерывный результат, например, вы хотите рандомизировать количество золотых монет, найденных в сундуке с сокровищами, и вы хотите, чтобы можно было получить любое число от 1 до 100, но сделать меньшие числа более вероятными. Использование метода массива поплавков для этого потребует, чтобы вы установили массив из 100 поплавков (т. е. секций на бумажной полосе), что громоздко; и если вы не ограничены целыми числами, а хотите получить любое число в диапазоне, такой подход использовать невозможно.

Для получения непрерывных результатов лучше использовать AnimationCurve для преобразования "сырого" случайного значения в "взвешенное"; рисуя разные формы кривых, вы можете получить разные веса. Код также проще писать:

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

Необработанное случайное значение от 0 до 1 выбирается путем чтения из Random.value. Затем он передается в curve.Evaluate(), который обрабатывает его как горизонтальную координату и возвращает соответствующую вертикальную координату кривой в этом горизонтальном положении. Пологие участки кривой имеют больше шансов быть выбранными, а более крутые — меньше.

Линейная кривая вообще не взвешивает значения; горизонтальная координата равна вертикальной координате для каждой точки на кривой.
Линейная кривая вообще не взвешивает значения; горизонтальная координата равна вертикальной координате для каждой точки на кривой.
Эта кривая более пологая в начале, а затем круче в конце, поэтому она имеет большую вероятность низких значений и меньшую вероятность высоких значений. Вы можете видеть, что высота кривой на линии, где x = 0,5, составляет около 0,25, что означает, что существует 50% вероятность получить значение от 0 до 0,25..
Эта кривая более пологая в начале, а затем круче в конце, поэтому она имеет большую вероятность низких значений и меньшую вероятность высоких значений. Вы можете видеть, что высота кривой на линии, где x = 0,5, составляет около 0,25, что означает, что существует 50% вероятность получить значение от 0 до 0,25.
Эта кривая пологая как в начале, так и в конце, что делает значения, близкие к крайним значениям, более распространенными, и крутая в середине, что делает эти значения редкими. Обратите также внимание, что в этой кривой значения высоты были смещены вверх: нижняя часть кривой равна 1, а верхняя часть кривой равна 10, что означает, что значения, полученные кривой, будут находиться в диапазоне 1-10. , а не 0-1, как предыдущие кривые.
Эта кривая пологая как в начале, так и в конце, что делает значения, близкие к крайним значениям, более распространенными, и крутая в середине, что делает эти значения редкими. Обратите также внимание, что в этой кривой значения высоты были смещены вверх: нижняя часть кривой равна 1, а верхняя часть кривой равна 10, что означает, что значения, полученные кривой, будут находиться в диапазоне 1-10. , а не 0-1, как предыдущие кривые.

Обратите внимание, что эти кривые не являются кривыми распределения вероятностей, которые можно найти в руководстве по теории вероятностей, а больше похожи на обратные кумулятивные кривые вероятности.

Определив общедоступную переменную AnimationCurve в одном из ваших скриптовA фрагмент кода, который позволяет вам создавать свои собственные компоненты, запускать игровые события, изменять свойства компонентов с течением времени и реагировать на ввод данных пользователем любым удобным для вас способом. Подробнее
Посмотрите в Словарь
, вы сможете увидеть и отредактируйте кривую с помощью Inspectorокна Unity, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет вам проверять и отредактируйте значения. Подробнее
Просматривайте в окне Словарь
визуально, вместо того, чтобы вычислять значения.

Этот метод создает числа с плавающей запятой. Если вы хотите вычислить целочисленный результат — например, вам нужно 82 золотых монеты, а не 82,1214 золотых монеты, — вы можете просто передать вычисленное значение в такую ​​функцию, как Mathf.RoundToInt().

Перемешивание списка

Обычная игровая механика заключается в том, чтобы выбирать из известного набора предметов, но они появляются в случайном порядке. Например, колоду карт обычно перемешивают, чтобы они не вытягивались в предсказуемой последовательности. Вы можете перетасовать элементы в массиве, посетив каждый элемент и заменив его другим элементом со случайным индексом в массиве:-

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

Выбор из набора элементов без повторения

Распространенной задачей является случайный выбор нескольких элементов из набора, не выбирая один и тот же элемент более одного раза. Например, вы можете захотеть сгенерировать несколько NPC в случайных точках возрождения, но убедитесь, что в каждой точке генерируется только один NPC. Это можно сделать, перебирая элементы по порядку, принимая случайное решение о том, будет ли он добавлен в выбранный набор. При посещении каждого элемента вероятность того, что он будет выбран, равна количеству еще необходимых элементов, деленному на число, из которого еще можно выбрать.

В качестве примера предположим, что доступно десять точек возрождения, но нужно выбрать только пять. Вероятность выбора первого предмета будет 5/10 или 0,5. Если он выбран, то вероятность для второго элемента будет 4 / 9 или 0,44 (т. е. еще нужны четыре элемента, осталось девять на выбор). Однако, если первое не было выбрано, то вероятность второго будет 5/9 или 0,56 (т. е. пять еще нужно, девять осталось на выбор). Так продолжается до тех пор, пока набор не будет содержать пять необходимых предметов. Вы можете сделать это в коде следующим образом: -

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

Обратите внимание, что, несмотря на случайный выбор, элементы в выбранном наборе будут располагаться в том же порядке, что и в исходном массиве. Если элементы должны использоваться по одному в определенной последовательности, порядок может сделать их частично предсказуемыми, поэтому может потребоваться перетасовать массив перед использованием.

Случайные точки в пространстве

Случайную точку в кубическом объеме можно выбрать, установив для каждого компонента Vector3 значение, возвращаемое Random.value:-

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

Это дает точку внутри куба со стороной в одну единицу длины. Куб можно масштабировать, просто умножая компоненты X, Y и Z вектора на желаемые длины сторон. Если одна из осей установлена ​​на ноль, точка всегда будет лежать в пределах одной плоскости. Например, выбор случайной точки на «земле» обычно заключается в произвольной установке компонентов X и Z и установке компонента Y равным нулю.

Если объем представляет собой сферу (т. е. если вам нужна случайная точка в пределах заданного радиуса от исходной точки), вы можете использовать Random.insideUnitSphere, умноженный на желаемый радиус:-

` var randWithinRadius = Random.insideUnitSphere * radius;`

Обратите внимание, что если вы установите один из компонентов результирующего вектора равным нулю, вы не получите правильную случайную точку внутри круга. Хотя точка действительно случайна и находится в пределах правильного радиуса, вероятность сильно смещена в сторону центра круга, и поэтому точки будут распределены очень неравномерно. Вместо этого для этой задачи следует использовать Random.insideUnitCircle:-

`var randWithinCircle = Random.insideUnitCircle * radius;`
Вы можете отблагодарить автора, за перевод документации на русский язык. ₽ Спасибо
Руководство Unity 2021.3