Как стать автором
Обновить

Комментарии 30

Таким образом мы избавляемся от большого количества головной боли, а наш компонент приобретает совсем другой вид
Создать непонятный класс, в котором есть непонятная ссылка на непонятный объект MonoBehaviour, на котором выполняется корутина — это избавление от головной боли? Мне работа с корутинами в Unity тоже не особо нравится, но я бы это решение не назвал «избавлением», т.к. оно немало новых проблем привносит.
Согласен с вами.
Но, как по мне, ваше замечание справедливо только если таких компонентов один/два/три/мало. Тогда обертка бесполезна. А когда проект достаточно большой и компонентов много, данный подход обретает смысл.
Используйте async / await

Я такой штукой пользуюсь:


  public static Coroutine InvokeDelegate(this MonoBehaviour mn, Action func, float time) {
        return mn.StartCoroutine(InvokeDelegateCor(func, time));
    }

    private static IEnumerator InvokeDelegateCor(Action func, float time) {
        yield return new WaitForSeconds(time);
        func();
    }

public static Coroutine InvokeDelegate(this MonoBehaviour mn, Action<float> func, float time, Action endFunc = null) {
        return mn.StartCoroutine(InvokeDelegateCor(func, time, endFunc));
    }

    private static IEnumerator InvokeDelegateCor(Action<float> func, float time, Action endFunc) {
        var timer = 0f;
        while (timer <= time) {
            func(timer / time);
            yield return null;
            timer += Time.deltaTime;
        }

        func(1f);
        if (endFunc != null)
            endFunc();
    }

Заменяет 99% таймеров

func(1f) вызвается 2 раза (иногда, почти невероятно), endFunc запаздывает на время кадра. Предполагаю, баги найдутся только после запуска в прод.

func(1f) может быть иногда два раза вызовется, совсем не всегда. Время кадров ну очень редко ровно в единицу просуммируется. Поэтому, чтобы ТОЧНО вызвалось — вызываю принудительно.

ну так там надо убрать равно из while (timer <= time) и все станет логичным.
начало хорошее, но есть и более эффективные способы работы с Coroutine
В стать я описал лишь один из нескольких вариантов, которые использую в зависимости от требований, размера и прочих свойств проекта. Буду признателен, есть поделитесь вашими.
Я это делал так habr.com/ru/post/352296

Сейчас я полностью перешел на acyns/await

Спасибо. Изучу.
А можете дать ссылочку почитать об это? acyns/await реализованы спецефично для unity?

Да, там хватает специфики. По умолчанию, они не поддерживают работу с AsyncOperation в Unity. Можете написать сами или использовать готовые реализации.


Вот несколько ссылок:



Интересное замечание из reddit’а:


One thing we noticed is that the Async methods continue executing when you stop the game in the editor..which can be really really bad! For example, if you have an async method that waits X seconds before destroying something — if you stop the game before that happens, your object will be destroyed in edit mode instead of play mode…

I have brought this up on the forum but just been met with 'thats just how c# works!' comments (which is technically correct, but not what you expect when you enter play mode and exit playmode), no developer response.
Спасибо большое
начало хорошее, но есть и более эффективные способы работы с Coroutine

Например, отказ от их использования.
Типа того) я потому и написал, что перешел на async/await.
Главное понимать, в просто виде без Task.Run это все работает в основном потоке Unity, т.е. также как Coroutine.
И да как выше писали, асинхронные операции не остановятся при выгрузке сцены, особенно это касается While(true) {await}. В этом случае надо использовать (да собственно и в других тоже) механизм CancellationTokenSource
На моей практике, достаточно часто получалось так, что при вызове строковой перегрузки StopCoroutine не происходило ровным счетом ничего. Корутина продолжала выполняться.

На самом деле совпадение что оно вообще иногда останавливалось. Строковая строка вовсе не обязательно обращается к тому же корутину что был начат.
Да, именно так и есть. :)
Я бы советовал не использовать корутины. Дешевле выйдет в итоге.
У меня пока что особых проблем не было с корутинами.
Хотелось бы узнать на чём основан ваш совет.
Это пока вы их делаете один. А когда у вас в команде несколько человек — «пиши пропало». Например, вы на больничном, а тут прилетает таска «срочно переделать ваш код» и ее отдают джуниору, поскольку нужно срочно, а у него чешутся руки — задача-то интересная. Через неделю вы приходите, и не делаете кодеревью этого кода, поскольку не знаете, что он был исправлен, и поскольку вам с порога прилетает куча задач, которые накопились за неделю, и которые можете сделать только вы. После нескольких таких итераций корутины выходят из под контроля, и даже черти в аду начинают креститься, когда им предлагают посмотреть на этот код.
срочно переделать ваш код

Если вы подразумеваете саму обертку, то это вряд ли. Она у нас уже давно обкатана и лежит в виде DLL с доками и прочим.


Есть более весомые аргументы?

Логику.Проблема не в коде планировщиков заданий корутин, проблема во взаимном пересечении множественных корутин, реализующих отложенную логику, периодические события и так далее. Еще один аргумент… Вы писали, писали логику… Прошло несколько месяцев. Уверен, что вспомнить как он работает, вы не сможете.
Вы можете сказать, что у вас с этим нет проблем, и я даже вам поверю (я бы и сам так сказал, а потом бы еще и доказал, если нужно было бы). Но вот советовать другим, я бы не стал. Это примерно как советовать попробовать ужасно ядовитое блюдо, которое ты ел сам и не отравился.

Возможно вы упустили (или я не достаточно явно об этом дал знать), но я не топлю за использование корутин в противовес другим техникам. И, от части, поддерживаю ваше мнение против них.
Суть статьи — предложить удобную обертку желающим пользоваться корутинами. Не более того.


Как уже писал выше:


В статье я описал лишь один из нескольких вариантов, которые использую в зависимости от требований, размера и прочих свойств проекта.


А об аргументах против корутин я вас спрашивал лишь для того, чтобы узнать ваше мнение и, если оно весомое, читающие всё это после нас увидят и, возможно, задумаются об альтернативах.
UniRx вам в помощь.
Благодарю, но это абсолютно не то, что мне нужно.
Очень полезно, спасибо. Я никак не мог понять, например, почему не останавливается корутина, пока не прочел эту статью, останавливал через дремучий лес. А тут все ясно и понятно, да и смотрится красиво)

Рад помочь.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории