При разработке игры нам частенько может понадобиться элемент случайности. Случайный набор предметов в сундуке, вероятность критического урона или "уворота", случайное место появление врага и тому подобное.
Например, в играх частенько урон представлен в виде диапазона чисел или иными словами интервала значений. При атаке врага, ему наносится урон равный случайному значению из этого диапазона.
Генератор случайных чисел в C# и Unity
В языке C# есть специальная функция для генерации случайных чисел из заданного диапазона Random.Range(). Случайный урон можно легко получить вписав в эту функцию минимальное и максимальное значение урона через запятую.
Но у этой функции есть интересная особенность. Когда функция Random.Range работает с целыми числами типа int, верхнюю границу она не включает в диапазон возможных значений. А вот если будет работать с дробными числами, то включает.
Поэтому, если мы хотим, чтобы максимальное значение урона тоже выпадало, но при этом делать дробное значение урона не хотим, то не забываем добавить единицу.
Математическая функция: Округление
Частенько нам, при работе с дробными числами, может понадобиться функция округления. Например, мы можем не прибавлять единицу, а просто пользоваться дробными значениями, которые потом будем округлять до целых.
Когда мы в первой статье говорили о типах данных, то использовали приведение типа float к типу int. Его тоже можно использовать для округления, но тогда мы максимального значения опять не получим. Приведения числа типа float к числу типа int просто отбрасывает дробную часть.
Есть ещё функция округления Mathf.Round(), которая на выходе сохраняет тип данных, поэтому с дробными числами её использовать не всегда удобно - придётся самостоятельно делать приведение к int.
Но, что если, мы захотим сделать урон в виде дробных значений, а нам не нужна такая точность в 6 знаков? Есть в библиотеке System функция округления до определенного порядка Math.Round(), но она работает со значениями типа double. Придётся приводить float к double (это произойдёт автоматически), а потом обратно во float.
Я предпочёл бы, в данном случае, умножить на 100, округлить и просто поделить на 100. Результат такой же. Выглядит проще. :)
Тип данных double, который является более точным аналогом типа float и занимает больше места в памяти, мы как правило и не используем никогда.
Цикл с условием while
Мы уже рассмотрели условный оператор if и цикл for. В цикле for можно зациклить проверку какого-либо условия на любое желаемое количество раз и по сути тоже получится "цикл с условием". Но, что если мы хотим непременно дождаться выполнения условия, сколько бы повторений цикла нам не потребовалось? Или вообще хотим, чтобы цикл выполнялся бесконечно. Тут то нам и пригодится цикл while ().
В качестве аргумента в операторе цикла while указывается условное выражение или переменная типа bool. While переводится как "до тех пор", "пока". Соответственно, пока аргумент цикла while имеет значение true, будет выполняться тело цикла бесконечное количество раз, каждый раз проверяя - не стал ли аргумент false.
Главная проблема и опасность цикла while кроется в бесконечности выполнения. Если не предусмотреть, чтобы условие цикла рано или поздно стало false, то мы получим бесконечный цикл, который приведёт к зависанию программы. Поскольку этот цикл никогда не закончится, то программа никогда не перейдёт к следующему шагу и зависнет на текущем шаге.
Поэтому цикл while для постоянной проверки здоровья нам не очень-то подходит, если только не сделать эту проверку через определенные промежутки времени или через определенное количество кадров. В обычном методе мы этого сделать не сможем, зато сможем сделать в асинхронном методе, добавив команду ожидания.
Цикл с условием в обычном методе нужно использовать аккуратно и всегда предусматривать условие выхода из него. Это можно сделать, например, с помощью оператора break.
Есть ещё полезный оператор continue, который прерывает не весь цикл, а только данную его итерацию, но он применяется довольно редко.
Как правило цикл while применяется в асинхронных циклах, либо в корутинах. В большинстве случаев хватает и циклов for / foreach. Но знать про него и про его подводные камни, при использовании в обычных методах, надо обязательно - это база! :)
А вот тут вся серия статей по базе C# для Unity: