#c# #loops #unity3d #coroutine
#c# #петли #unity3d #сопрограмма
Вопрос:
Итак, вот в чем дело. У меня есть игра, в которой у меня есть спаунер — для создания препятствий. И я хочу после каждого 5-го препятствия увеличивать скорость. Пример: 1-е, 2-е, 3-е, 4-е, 5-е препятствия имеют скорость по умолчанию = 5, и я хочу, чтобы 6-е, 7-е, 8-е, 9-е, 10-е имели увеличенную скорость до скорости = 10 и т.д. У меня уже есть несколько вложенных операторов if, но я хочу бесконечно увеличивать скорость, например, чтобы иметь speed = 1000 для 100-го препятствия. Вот мой код:
IEnumerator SpawnObstacles()
{
int i = 0;
do
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
Destroy(obstacle, 10f);
i ;
if(i >= 10)
{
IncreaseSpeed();
if(i >= 20)
{
IncreaseSpeed();
if(i >= 30)
{
IncreaseSpeed();
}
}
}
}
while (true);
}
private void IncreaseSpeed()
{
Obstacle obs = FindObjectOfType<Obstacle>();
obs.speed = 5f;
}
Комментарии:
1. Вы можете использовать modulo для тестирования для каждой 5-й итерации:
if (i % 5 == 0) IncreaseSpeed()
или просто установите скорость в зависимости от номера итерации:obj.speed = (i/5) * 5f
2. Обратите внимание, что вы сказали каждые 5, но ваши
if
s безумно увеличивают скорость после каждых 10.. (Ваша скорость составляет 5,5,5,5,5,5,5,5,5,5,5,15,25,35,45,55,65,75,85,95,105,125,145,165 …)
Ответ №1:
Оператор modulo %
помогает с подобными вещами. Это дает оставшуюся часть операции деления, например:
3%5 is 3
4%5 is 4
5%5 is 0
6%5 is 1
7%5 is 2
8%5 is 3
9%5 is 4
10%5 is 0
Так что, если ваш x
параметр начинается с 0, и вы хотите увеличивать скорость каждые 5, вы просто смотрите, когда модуль равен 4..
x
может быть так высоко, как вам нравится (ну, int.MaxValue), но по модулю всегда будет 0 ..4:
//do some stuff
//should we increase speed?
if(x % 5 == 4)
IncreaseSpeed();
Удобный инструмент и для создания круглых массивов.. someArray[i % someArray.Length]
никогда не выйдет за пределы, потому что результат по модулю всегда от 0 до единицы меньше длины
Ответ №2:
Вместо этого вы могли бы сделать либо :
- Отслеживайте, сколько экземпляров препятствий вы создали до сих пор, используя переменную (возможно, статическую переменную https://www.c-sharpcorner.com/UploadFile/1ce252/static-variables-and-static-methods-in-C-Sharp / ) и убедитесь, что вы просто увеличиваете скорость для каждых 5 экземпляров , используя modulo
%
. Вы можете ознакомиться с более подробной информацией здесь: https://blog.mattclemente.com/2019/07/12/modulus-operator-modulo-operation.html
Краткое введение в модули:
//It essentially shows the rest of a division
5 / 5 == 1
//Since there's no rest there,
5 % 5 == 0
//But in the case of where there is a rest
6 / 5 == 1 (Rest 1)
//Hence
6 % 5 == 1
//Other examples :
7 % 5 == 2
8 % 5 == 3
9 % 5 == 4
10 % 5 == 0 //!! The result is back to zero here as 10/5 == 2 with no Rest
- Реализуйте рекурсивную функцию, которая находится в объекте, который появляется в другом объекте с теми же атрибутами, но передает параметр, который указывает, сколько экземпляров было создано до сих пор, и проверьте, является ли это 5-м экземпляром, если это так, добавьте к нему скорость.
Ответ №3:
В любом случае у вас есть сопрограмма в бесконечном цикле … почему бы просто не сделать
IEnumerator SpawnObstacles()
{
do
{
for(var x = 0; x < 5; x )
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
Destroy(obstacle, 10f);
}
// These lines are automatically reached after every 5 iterations
// no need for any módulo or other magic check
Obstacle obs = FindObjectOfType<Obstacle>();
obs.speed = 5f;
}
while (true);
}
Или, поскольку я не уверен во всей этой FindObjectWithTag
штуке… на самом деле мне кажется, что это тот же объект, который вы создаете, верно? Так почему бы просто не
IEnumerator SpawnObstacles()
{
var speed = 5;
do
{
for(var x = 0; x < 5; x )
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
obstacle.GetComponent<Obstacle>().speed = speed;
Destroy(obstacle, 10f);
}
// These lines are automatically reached after every 5 iterations
// no need for any módulo or other magic check
speed = 5f;
}
while (true);
}
Хотя для меня остается немного неясным, как именно ваша скорость должна расти. Из вашего описания звучит так, как будто вы хотите добавлять 5
после каждой группы итераций .. однако это означало бы, что у вас есть speed = 100 (20 * 5) для 100-го объекта .. а не speed = 1000, как вы написали
Ответ №4:
Самое простое, что я могу придумать, — это установить счетчик для порожденных препятствий и увеличить скорость после того, как она достигнет 5, и сбросить счетчик на ноль. На самом деле вам не нужно вдаваться в причудливые вещи для чего-то настолько простого, просто используйте оператор if для проверки счетчика.Надеюсь, я помог, ваше здоровье!