[EXP] Unity 3d - Отложенные действия. Invoke VS Coroutines.
Довольно часто в играх существует необходимость выполнять какие-либо действия отложенным образом, в том числе и по времени. Для этого в Unity 3d предусмотрены методы:
• Invoke(string methodName, float time);
• InvokeRepeating(string Method Name, float time, float repeatRate);
• CancelInvoke(); и CancelInvoke(string methodName);
Invoke полагается на Time.timeScale. То есть, если мы вызываем Invoke("SomeMethod", 2f) при Time.timeScale = 0.5, то SomeMethod() начнет выполняться через 4 секунды, а при 0 - не начнет выполняться вовсе.
Не одним Invoke-ом сыты, ведь есть еще способы отложено выполнить действия, например таймеры или корутины. Вот на них, я пожалуй и остановлюсь.
Корутины в данном контексте мне всегда казались очень производительными, практичными и более знакомыми с точки зрения: "А что под капотом?", но не столь удобными в использовании, как тот же Invoke, ведь приходится жертвовать парой строчек кода... А ещё, корутины решают проблему с отложенным запуском при различных значениях Time.timeScale.
Вот как выглядит отложенный запуск с использованием Coroutines:
Вот так может выглядеть использование Invoke:
Но, возвращаясь к изначальной теме, кто круче то? В этом вопросе я учитываю такие критерии как:
• Производительность
• Удобство
• Гибкость
Я думаю, некоторые выводы об удобстве и гибкости сделаны (о них чуть позже). А вот с производительностью дела обстоят по-интереснее...
Тестирование производительности
Для тестирования я не придумал ничего лучше, как создать 5940 сущностей, которые одновременно будут вызывать отложенное действие через Invoke и Coroutine, и наблюдать за этим в профайлере.
Из тестов можно сделать вывод, что Invoke оказался производительней... А WaitForSecondsRealtime вносит свою лепту в общую картину.
Заключение
Учитывая всё выше сказанное, я склоняюсь к тому, что Invoke более прост в использовании и, как оказывается, производительней, а корутины более многозадачные и гибкие.
Лично мне отдавать предпочтение чему-то одному не приходится - всегда стоит исходить из ситуации и решаемой задачи. Для простых задач можно использовать Invoke, а для более трудных, требующих гибкого подхода можно использовать Coroutine, жертвуя малой каплей производительности.
Надеюсь, статья была вам интересна и полезна. Если у вас есть иной личный опыт использования Invoke и Coroutine, будет интересно узнать что-то новое. Всем мир)
P.S.: Первая статья на DTF. Если у вас есть какие-либо пожелания, оценка или совет формата подачи, я открыт к критике.
Invoke обладает еще не очень удобным моментом, он выполнится даже если объект выключили, мне обычно удобнее предполагать что выключенный объект ничего не будет делать. Но где то может пригодиться обратное.
Хм, действительно это камень в огород Invoke) Получается, теперь это нужно учитывать в голове. Спасибо за обратную связь!
Не люблю корутины, их вызов интуитивно менее понятен, чем инвоки, поэтому когда нужно использую Invoke)
Если ситуация позволяет, почему бы и нет) Спасибо за комментарий!
Комментарий недоступен