Unity 'StartCoroutine' не запускается дважды, когда IEnumerator передается как переменная? - PullRequest
2 голосов
/ 04 февраля 2020

Итак, я столкнулся с чем-то странным, когда использовал сопрограмму в Unity для симуляции NP C (идет к цели, бездействует в течение x секунд, идет к цели - повторить--).

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

Почему это так работает? Что происходит "под капотом"? Я не могу обернуть голову, почему это так, и это меня беспокоит.

Ниже моего IEnumerator метода, который имитирует время простоя.

private IEnumerator sitIdle()
{
    var timeToWait = GetIdleTime();
    _isIdle = true;
    yield return new WaitForSeconds(timeToWait);
    _isIdle = false;
} 

Если это называется второй раз по сценарию № 1 (ниже), он запускается, как и ожидалось, когда вызывается несколько раз. Он просто повторяет процесс снова и снова.

Если, однако, если он вызывается в соответствии со Сценарием № 2 (ниже) в качестве переменной, он запускается один раз, но отказывается вводить второй раз и просто показывает ' пропустите его в коде.

void LateUpdate()
    {
        _idleRoutine = sitIdle; //this is not actually in the late update, just moved here for reference.

        if (_agent.hasPath)
        {
            if (isTouchingTarget())
            {
                StartCoroutine(sitIdle2()); //Scenario #1

                StartCoroutine(_idleRoutine); //Scenario #2

                _currentTarget = null; 
                _agent.ResetPath();
            }
        }

Tl; dr: StartCoroutine (переменная для IEnumerator) не повторяется, в то время как StartCoroutine (IEnumerator ()) работает нормально, почему я не могу передать IEnumerator в качестве переменной?

1 Ответ

3 голосов
/ 04 февраля 2020

Возвращаемым значением SitIdle() является IEnumerator. IEnumerator не повторяются, когда они завершены и у них не осталось итераций, что StartCoroutine говорит Unity. Каждый раз, когда сопрограмма возобновляется на yield, выполняется еще одна итерация, которую Unity предписывает сопрограмме выполнить.

Если вы действительно хотите сохранить сопрограмму как переменную, чтобы вы могли выбирать между тем или другим, вы может сохранить интересующий вас метод в качестве делегата, а затем вызвать его, чтобы получить ваш fre sh IEnumerator:

IEnumerator sitIdle()
{
    var timeToWait = GetIdleTime();
    _isIdle = true;
    yield return new WaitForSeconds(timeToWait);
    _isIdle = false;
}  

IEnumerator sitIdleAlternative()
{
    var timeToWait = GetIdleTime() + 2f;
    _isIdle = true;
    yield return new WaitForSeconds(timeToWait);
    _isIdle = false;
}

delegate IEnumerator IdleDelegate ();

IdleDelegate _idleRoutine;

void LateUpdate()
{
    _idleRoutine = new IdleDelegate(sitIdleAlternative); //this is not actually in the late update, just moved here for reference.

    _idleRoutine = new IdleDelegate(sitIdle);

    if (_agent.hasPath)
    {
        if (isTouchingTarget())
        {
            StartCoroutine(sitIdle2()); //Scenario #1

            StartCoroutine(_idleRoutine()); //Scenario #2

            _currentTarget = null; 
            _agent.ResetPath();
        }
    }
}
...