Увеличение в цикле или операторе if

#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:

Вместо этого вы могли бы сделать либо :

Краткое введение в модули:

 //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 для проверки счетчика.Надеюсь, я помог, ваше здоровье!