(Исправлено!) HTML скушал "<T> "- как тег, а я и не заметил...приношу извинения.
Заметка написана в роли простого ответа на вопрос моему товарищу-геймдизайнеру. Не думаю, что она будет полезна, поскольку уровень у неё совсем лайтовый. Но все же раз руки дошли написать это, то выложу.
Речь далее пойдет о том как получить объекты с заданной процентной вероятностью.
Я, честно говоря, даже не знаю, что тут объяснять поэтому поленюсь и напишу листинг кода прямо здесь, не компилируя, ведь главное суть.
Итак, создаем файл (скрипт), назовем его Randomizer.cs
Заметка написана в роли простого ответа на вопрос моему товарищу-геймдизайнеру. Не думаю, что она будет полезна, поскольку уровень у неё совсем лайтовый. Но все же раз руки дошли написать это, то выложу.
Речь далее пойдет о том как получить объекты с заданной процентной вероятностью.
Я, честно говоря, даже не знаю, что тут объяснять поэтому поленюсь и напишу листинг кода прямо здесь, не компилируя, ведь главное суть.
Итак, создаем файл (скрипт), назовем его Randomizer.cs
using UnityEngine;
using System.Collections.Generic;
public class Randomizer
{
/*
* на вход подается шанс(вероятность) объекта в процентах от 0 до 100
* можно использовать для одиночных объектов с заданной вероятностью
* предположим: выпадет ли лут с моба? подаем вероятность в функцию,
* она в свою очеред возвращает true или false
*/
public static bool IsGet(int chance)
{
int rand = Random.Range(0, 100);
return (100 - chance <= rand) ? true : false;
}
/*
* теперь сложнее ситуация
* на вход подаем массив объектов какого-либо класса
* предположим массив изображений и случайным образом
* с равной вероятностью функция вернет какое либо изображение
* из этого массива
*/
public static T GetOne<T>(T[] objects)
{
int[] chances = new int[objects.Length];
for(int i = 0; i < chances.Length; i++)
chances[i] = 1;
return GetOne(objects, chances);
}
/*
* следующая ситуация у нас есть массив тех самых изображений,
* но у каждого из них имеется свой шанс появления
* в зависимости от этих значений функция вернет объект
* случайным образом, но с рассчитаной вероятностью
*/
public static T GetOne<T>(T[] objects, int[] chances)
{
int rand = Random.Range(0, GetChancesSum(chances));
int i = GetObjectIndex(chances, rand);
return objects[i];
}
/*
* и еще одна ситуация все тоже что и в предыдущей, но!
* в данном случае вероятности объектов не общие, а у каждого
* своя от 0 до 100% поэтому на выходе мы получаем массив объектов
*/
public static T[] GetMultiply<T>(T[] objects, int[] chances)
{
List<T> array = new List<T>();
for(int i = 0; i < chances.Length; i++)
{
if(IsGet(chances[i]))
array.Add(objects[i]);
}
return array.ToArray();
}
private static int GetChancesSum(int[] chances)
{
int sum = 0;
foreach(int chance in chances)
sum += chance;
return sum + 1;
}
private static int GetObjectIndex(int[] chances, int rand)
{
int i = 0;
int sum = chances[i];
while(sum < rand)
{
i++;
sum += chances[i];
}
return i;
}
}
Чтобы не раздувать статью и листинг, не стал писать обработчики ошибок, не предусмотрел установку вероятностей в float. И вообще в этой статье хотел пояснить человеку далекому от программирования как же "задать вероятность в юнити".
А теперь подводя итог поясню суть всего написанного выше:
1. Получить случайное число: Random.Range(min, max), где min - число нижняя граница значения случайного числа, которое мы хотим получить, а max - его верхняя граница.
2. Получить объект с вероятностью N% - для этого пишем функцию, которая вернет true или false. В теле функции получаем рандомное число от 1 до 100, далее проверяем если шанс(N) больше либо равен полученному рандомному числу, то возвращаем true в противном случае false. Другими словами: мы имеем отрезок от 0 до N и от N до 100, а рандомайзер случайным образом выбирает значение в пределах всех значений этого отрезка, исключая ноль. Дальше мы проверяем на каком отрезке лежит наше число. Вот и все.
3. Получить объект из массива объектов с заданными вероятностями. Тут все тоже самое, только отрезки создаются для каждого объекта и раскладываются друг за другом в одну линию. Далее проверяем на какой отрезок попала точка и возвращаем объект которому принадлежал этот отрезок.
Всем кто удосужился прочитать, спасибо за внимание!
А теперь подводя итог поясню суть всего написанного выше:
1. Получить случайное число: Random.Range(min, max), где min - число нижняя граница значения случайного числа, которое мы хотим получить, а max - его верхняя граница.
2. Получить объект с вероятностью N% - для этого пишем функцию, которая вернет true или false. В теле функции получаем рандомное число от 1 до 100, далее проверяем если шанс(N) больше либо равен полученному рандомному числу, то возвращаем true в противном случае false. Другими словами: мы имеем отрезок от 0 до N и от N до 100, а рандомайзер случайным образом выбирает значение в пределах всех значений этого отрезка, исключая ноль. Дальше мы проверяем на каком отрезке лежит наше число. Вот и все.
3. Получить объект из массива объектов с заданными вероятностями. Тут все тоже самое, только отрезки создаются для каждого объекта и раскладываются друг за другом в одну линию. Далее проверяем на какой отрезок попала точка и возвращаем объект которому принадлежал этот отрезок.
Всем кто удосужился прочитать, спасибо за внимание!
Комментариев нет:
Отправить комментарий