9/11/2014

Unity Random.Range

(Исправлено!) HTML скушал "<T> "- как тег, а я и не заметил...приношу извинения.
Заметка написана в роли простого ответа на вопрос моему товарищу-геймдизайнеру. Не думаю, что она будет полезна, поскольку уровень у неё совсем лайтовый. Но все же раз руки дошли написать это, то выложу.



Речь далее пойдет о том как получить объекты с заданной процентной вероятностью.
Я, честно говоря, даже не знаю, что тут объяснять поэтому поленюсь и напишу листинг кода прямо здесь, не компилируя, ведь главное суть.

Итак, создаем файл (скрипт), назовем его 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. Получить объект из массива объектов с заданными вероятностями. Тут все тоже самое, только отрезки создаются для каждого объекта и раскладываются друг за другом в одну линию. Далее проверяем на какой отрезок попала точка и возвращаем объект которому принадлежал этот отрезок.

Всем кто удосужился прочитать, спасибо за внимание!

Комментариев нет:

Отправить комментарий