Сброс повторяющейся задержки сопрограммы - PullRequest
0 голосов
/ 03 мая 2018

Я использую сопрограмму, чтобы настроить задержку повторения следующим образом.

В моем Пробуждении у меня есть

StartCoroutine(RandomMove());

А потом еще дальше

IEnumerator RandomMove()
    {
       while (true)
        {
            // print(Time.time);
            yield return new WaitForSeconds(foo);
            // print(Time.time);
        }

    }

где 'foo' - это случайное значение с плавающей точкой, которое я меняю при каждой итерации. Допустим, foo равен 10 секундам, и частично через задержку мне нужно сбросить задержку, чтобы она снова начала «обратный отсчет» с 10.

Как бы мне этого добиться? Должен ли я использовать таймер вместо этого?

Ответы [ 4 ]

0 голосов
/ 04 мая 2018

Хммм, это может что-то вроде этого тоже. Только для себя.

void Start() {
StartCoroutine(RepeatingFunction());
}

IEnumerator RepeatingFunction () {
yield return new WaitForSeconds(repeatTime);

StartCoroutine( RepeatingFunction() );
}

Как я понимаю вопрос. InvokeRepeating() тоже выбор.

0 голосов
/ 03 мая 2018

Может быть, это потому, что вы каждый кадр ожидаете новых назначенных секунд?

Почему бы вам не сделать случайное число до выдачи ожидания и сохранить CustomYieldInstruction вместо выдачи нового экземпляра, поскольку он удаляет тот, который был раньше, что создает проблемы с памятью. Вы не заметите, что если вы выдадите return WaitForSeconds с постоянным значением, но, возможно, со случайным, это создает неоднозначность и сбрасывает таймер (см. Эту страницу оптимизации Unity, в разделе сопрограммы ). Быстрый пример:

public float foo;
public float min;
public float max;

void Awake()
{
    StartCoroutine(Countdown());
}

IEnumerator Countdown()
{
    while(true)
    {
        foo = Random.Range(min, max);
        WaitForSeconds wait = new WaitForSeconds(foo);
        yield return wait;
    }
}

Кроме того, решение @ ryeMoss кажется хорошим, чтобы остановить и перезапустить сопрограмму, если «foo» изменится.

Надеюсь, это поможет.

0 голосов
/ 04 мая 2018

Мне не нравится ни один из двух существующих ответов. Вот что я бы сделал:

Убить и перезапустить сопрограмму:

Мы начнем с этой части ответа killer_mech:

Coroutine myCoroutine;
void Awake() {
    myCoroutine = StartCoroutine(RandomMove());
}

Но мы собираемся обращаться с остальными по-другому. killer_mech никогда не делал ничего со ссылкой, кроме как постоянно переписывать ее.

Вот что мы делаем вместо этого:

public void resetRandomMove() {
    StopCoroutine(myCoroutine);
    myCoroutine = StartCoroutine(RandomMove());
}

Звоните в любое время, когда вам нужно сбросить его.

0 голосов
/ 03 мая 2018

Я бы предложил вам сначала сохранить Coroutine в переменной.

Coroutine myCoroutine;
void Awake()
{
 myCoroutine = StartCoroutine(RandomMove());
}

и измените функцию сопрограммы на

IEnumerator RandomMove()
{
            // print(Time.time);
            yield return new WaitForSeconds(foo);
            // print(Time.time);
            // Call your new coroutine here
            myCoroutine = StartCoroutine(RandomMove());
}

таким образом, у вас будет переменная сопрограммы для каждой итерации. Если вам нужно остановить сопрограмму, просто скажите:

StopCoroutine(myCoroutine);

в вашей функции в нужное время. Это позволит вам остановить сопрограмму посередине до окончания обратного отсчета. Также в конце сопрограммы она запустит новую сопрограмму с обновленной ссылкой. После завершения задания просто перезвоните с

myCoroutine = StartCoroutine(RandomMove());

Надеюсь, это решит вашу проблему. Да, вы можете сделать это с таймером и с булевым флагом, но я думаю, что использование сопрограммы намного проще. .

...