Всё про корутины в Unity 3D
HTML-код
- Опубликовано: 4 янв 2025
- Вся основная информация о корутинах в Unity 3D в одном видео. Что такое корутины, что писать после yield return, как пользоваться Start Coroutine и Stop Coroutine, для чего их можно применять, и прочие тонкости связанные с корутинами в Юнити
Patreon канала - / emeraldpowder
Наш Discord - / discord
На этом канале регулярно появляются новые видео, которые позволят тебе научиться создавать игры, или подарят новые идеи и вдохновение, если ты уже умеешь. Подписывайся!
Остались какие-то вопросы, пожелания, или идеи для других видео? Смело пиши в комментарии под видео
Очень долго боялся корутин. Спал со включённым светом, заглядывал под кровать перед сном, чтобы проверить, не сидит ли там какая-нибудь сопрограмма... а потом вырос и эти чудовища превратились в лучших друзей при разработке!
Спасибо автору за качественный материал без воды!
Жиза
Корутины наше всё. Для меня инфа не новая, но новичкам будет очень полезно. Спасибо за развивающий контент отличного качества. Его на рутюбе очень мало.
Полезный материал, думаю многие наконец перестанут бояться корутин)
Два любимых русскоязычных геймдев блогера в одном месте, мимими
Не думал тебя тут увидеть) Смотрю твои видео, спасибо что даёте такие ценные знания
Ничего не понял, автор слишком быстро показывает и тараторит. Не понимаю, откуда столько хвалебных отзывов.
@@KotleKettle смотрите документацию, там никто не тараторит и можно прочитать все детали
Было бы неплохо еще рассказать что такое IEnumerator, moveNext, current и Reset. Так сказать для полноты картины)
Это нативный C#. Вкратце IEnumerator- интерфейс перечисления. Current - выдать выбранный элемент списка. moveNext - Переключиться на следующий элемент списка. Reset - сбросить "счётчик" (начать перечисление с начала)
P.S
Это очень поверхностоное объяснение, лучше найдите статью на эту тему
@@zerocode2909 Я знаю ответ на вопрос, коммент к тому, чтобы зрителю об этом донести
@@gaitavr1992 Еще можно было бы рассказать, как тоже самое на ассемблере написать, для полного понимания))
@@valerii-barabanov-vvb Потом вот такие, как вы приходят на собеседования и не знают ничего о работе языка и движка. При чем тут ассемблер? Внутренности енумератора должен знать любой разработчик уровня мидл+. Вам лишь бы показывали как игру сделать за час да как пару скриптов накидать
@@gaitavr1992 Это совершенно разные уровни абстракции. У "таких как вы" сначала надо разобраться в енумераторе, а потом надо разобраться в компиляторе, Си подучить и ассемблер, потом научиться в хешредакторе программы писать, потом компьютеры собирать, а то так же непонятно, что корутина делает, пока не разбоерешся как электроны по проводам ходят. "Такие как вы", у вас вообще воспитание есть, что вы так обращаетесь к людям? "Таких как ВЫ" проводить собеседования вообще допускать нельзя. Какое, блять, ты вообще право имеешь меня с кем-то сравнивать, такиекаквыкать мне?
Вау, благодаря этому видео смог представить как можно улучшить игру, спасибо)
Четкий видос)
Еще бы про Async Await-ы такой же)
Наконец-то понял, как работать с корутинами, до этого видео посмотрел 2 других и там просто показали синтаксис, не больше. Спасибо!
Спасибо за видос! Когда начинал, никак не мог понять как всю логику запихнуть в апдейт, потом открыл корутины и жизнь стала проще
Когда только начинал в юнити, сразу же потребовалось создать спавнер врагов, но к сожалению не смог быстро отыскать нужную (и ПОНЯТНУЮ) инфу по корутинам в Unity. Наткнулся на Invoke и собственно им и пользовался (и придумывал много костылей), а оказывается всё было так просто. Спасибо!
Хоть я и повсеместно использовал корутины в своем коде, но я не знал, что с помощью них можно делать такие сложные последовательности анимаций! Спасибо за интересную инфу!
Спасибо за толковое и легкое донесение. Еще со временем когда только изучал Unity как-то корутины как "что-то нихрена непонятное и походу взрывоопасное" и использовал только в случаях крайней необходимости, теперь надо изучить их и попрактиковать! Спасибо!
Было бы хорошо еще посмотреть урок про много поточность в unity. А про корутины спасибо
Ultra-Money, ну, это обычную многопоточность в с# тогда надо смотреть (скорей всего). Таски и await async
Насколько я знаю, Unity не поддерживает многопоточность, и при попытке запустить ещё один поток выбрасывает исключение.
@@lulook2806 поддерживает.
@@ivanm71 async/await - механизм асинхронности и к многопоточности не имеет никакого отношения
@@hanmayujiro1433 я тред в юнити прекрасно создавал для сокетов
Очень много полезной информации в одном коротком видео. Спасибо!
Спасибо, то что нужно было в ролике, ты лучший!
Великолепная подача материала, большое спасибо!
Спасибо огромное. Благодаря Вам мой код сократится на множество строк.
Просто огонь! Пойду гляну что там еще на канале интересненького :D
очень здорово. долго искала такое видео
первый видео ролик где я понял меньше 30% материала, наверное куча инфы, автор постарался на славу
Давно ждал этого урока. Пока никто не объяснил что они такое зачем нужны и т.д. Спасибо
Твои уроки как всегда великолепны!)
удивило что ты сказал что корутины не так популярны среди новичков ) Мне казалось это основа основ)
Круто! Очень хорошо объяснил👍
Отдельное спасибо за хорошие субтитры
Стоило рассказать ещё про составление очередей корутин, вызов корутин по имени, передача параметров в корутины, хотя видео правда хорошее.
Спасибо огромное)
Из ролика понял, что можно запускать асинхронные задачи из корутин, что расширяет их область применения, очень даже. По-больше бы таких роликов на русском ютубе, и жизнь стала бы легче.
класс, спасибо за обучение
Спасибо, очень полезный материал. Так держать!Всё круто!
Очень крутые ролики у тебя))
Хотелось бы чтоб ты заснял курс для начинающих по unity, сам я андроид разработчик, но по твоим видео начинает симпатизировать и unity))
Спасибо)
Если есть опыт разработки то думаю курс для начинающих не нужен, там в юнити все довольно интуитивно
Оч классный ролик все понятно и интересно:3
12:30 Вот только корутину нельзя остановить с помощью StopCoroutine если она запустилась прямой ссылкой.
Хорошее видео. Отличная идея сделать отдельный класс с простыми корутинами на движение и прочее.
Ray marching в HDRP/URP! И кроме этого слелай просто видео про ray marching. Думаю будет круто.
Что я вынес с урока:
- корутина позволит тебе задерживать пчелочку на месте, а потом сделать чтобы она упала
- корутина сможет спаунить с пчелки монеты
- корутина заканчивается на тина, а ещё там всякие yield return ы есть, которые помогают процессы на время задерживать (на время или до выполнения какого -то условия)
Боже как же годно! Господа это лайк
Отличное видео, спасибо!
Братан, не плохо объяснил, но ошибка многих. Корутина регистрируется как ты и сказал в главном потоке Unity, но даже после остановки ее по мере выполнения кода или ручной остановки, ещё живёт в самом потоке, по этому с корутинами нужно быть осторожным. Они на первый взгляд не тяжёлые, но они очень даже дорогие и хоть этого часто не видно, но корутина сама по себе чуть замедляет выполнение кода, ну как я и сказал, она не дешёвая
MBSCore ну это потому что все данные в корутине живут пока она не завершится, в след. кадре.
чел, ты можешь запустить 10 000 корутин и ничего не упадёт. А можешь одним циклом while в Апдейте полностью скрашить приложение - теперь еще раз подумай насколько они "тяжёлые")
Шикарно. Лучшее объяснение из всех виданных как на русском, так и на английском ( :) скорость на пределе восприятия, информация очень плотно временами хочется поставить WaitForSecond (1.f);
Помню как то делал корутину содержащую таймер который должен был сбрасываться в 0 в случае если объект покидал триггер. Но он не сбрасывался. В итоге открыл для себя async await. Все возможности корутин есть и даже больше, синтаксис почти тот же + вроде, нет этих проблем с отключением компонента и продолжением выполнения процесса.
Отличный материал!!! С меня лайк+подписка
Как всегда шикарно )
6:29 - можно, плиз, ссылку на картинку?
@@hanmayujiro1433 не за что, обращайся)
Отличное видео, спасибо
9:05 ну... не сказал бы... иногда вместо ифов проверки более полезна или для убирания сообщения ошибки, если она не критична для тестирования, но мешает отслеживать что-то реально критичное ввиду спама в лог
Спасибо, хороший туториал
Оч годный контент, спасибо тебе огромное!
Есть в планах выпустить что-нибудь про свет в 3д?)
Ещё можно рассказать про параллельно-последовательное выполнение корутин
Какие есть способы приостановки выполнения корутины с последующим возобновлением? К примеру при появлении всплывающее подсказки на экране, объекты движущихся /анимированые с использованием корутин замерли
Вот это класс. Кучу пробелов устранил, благодаря этому видео.
Запиши, плиз, в таком же обзорном стиле видео по веб запросам, ради христа. Чтоб вначале вкратце о WWW (на них куча старого кода, уроков, плагинов и тд) и потом о UnityWebRequest'ах. В идеале с парочкой примеров, как заменять в устаревшем коде www на UnityWebRequest.
По этой теме на русском инфы почти никакой.
Если дело касается анимаций, уж тем более вещей, типа "сделать ui прозрачным со временем", лучше использовать DoTween. Корутины использую только если очень нужно выполнить методы по цепочке, с задержками, и эти методы не связаны с монобехейвером. Во всех остальных случаях - только DoTween, даже твой простой пример из видео занял строчек 15, через твины это делается одной. Я не плохой человек, мне нравятся твои видео, но зачем писать хорошие анимации не одной строчкой?)
Это скорее просто как пример, лёгкий для понимания.
@@homexp13 До меня только что дошло, что видео "про корутины", значит видео ок, а мой комментарий ни к селу ни к городу)
Привет, как насчёт видео обзора по probuilder unity.
Ожидание до нового фрейма помогло разбить генерацию чанков на мелкие задачи и пофиксить просадки фпс при подгрузке чанков (когда все выполнялось за 1 фрейм).
Короютины лучшее что можно придумать. Я с их помощью полностью логику с босса сделал
Dr Seedon корутины ))
В чём преимущество использования корутины для MoveForward, например, по сравнению с размещением его в Апдейте?
А корутина работает в фоновом режиме, или код после корутины будет работать только, когда корутина закончится?
Если ещё актуально, в фоновом режиме
Это аналог Thread?
Было бы полезно рассказать как использовать yield конструкцию для создания своих корутин, т.е. без MonoBehaviour. Как используется такая конструкция в C# например для обхода массива, или хотя бы как именно вызываются корутины в MonoBehaviour
Timur Bogotov зачем?! Это уже лишнее и касается уже программирования в целом, а не юнити.
Да, это тема широкая, в этом видео я решил не углубляться как в целом работают IEnumerator'ы и yield'ы. Но если про работу с коллекциями рассказывать то это уже скорее к С# чем к Unity относится, так что не в это видео
@@EmeraldPowder Да, всё верно. Наверное большинству это и не нужно
Случайно увидел это видео, в общем для новичков полезно. Но далеко не ВСЁ о корутинах!!!
Автор, зря вы про то что try/catch ВЕСЬ ГЕЙМДЕВ не использует, это далеко не так.
Про try/catch в корутинах важно было сказать что нельзя делать так:
private IEnumerator MyCoroutine()
{
try
{
yield return null;
Очень полезное видео!
Скажи пожалуйста, обязательно ли прерывать корутину после её выполнения с помощью break, или она прерывается сама после любого yield return?
Если не вызывать ее в Update, то она выполнится один раз до конца, брейком можно завершить заранее
@@trushkeen понял, спасибо
Было бы классно объяснить о корутине после коллизии
Полезно, спасибо
Отличный видос! А что за редактор кода используется? Уж очень приглянулся
Rider
JetBrains Rider называется, если вдруг кому тоже стало интересно
@@okely4755 спасибо
Покажи пожалуйста как реализовать FSM на unity.
Я прям рессмеялся когда узнал что можно вот так просто взять и вставить одну(!) строчку между двумя, и обойтись обычной корутиной, вместо того чтобы писать огромную функцию таймер с кучей архитектурных сложностей 😂😂😂
Скажите в чем разница между WaitForSeconds и Invoke ??
Объясни пожалуйста, что такое корутина "под капотом" как они связаны между собой и почему остановка корутины осуществляется, в том числе, через "break".
Это тоже тема интересная, но уже скорее не про юнити а про C#, да и тянет на отдельное видео
@@EmeraldPowder
был бы рад такому видео, так как впервые на детальное объяснение напоролся лишь спустя 2 года коммерческой разработки)
Корутины и асинхронные методы разные вещи?
А как сделать чтобы корутины не накладывались, допустим есть несколько обьектов при нажатии на которой он передвигается с помощью корутины с точки А в точку Б, у меня получается что пока он передвигается (допустим задал 5 секунд), я могу нажать на другой обьект и он тоже начнет свое движение. А мне нужно чтобы пока первый обьект не дошел до точки Б, другие обьекты не могли двигатся. Пробовал с переменной bool играя с true и false, что то не работает.
Я правильно понимаю, что это почти тоже самое, что генераторы или async/await в javascript? А то я про эти корутины слышал только из Kotlin
Да, в C# тоже есть async/await, и их даже можно использовать в Unity почти точно так же как и корутины. Но я привык к корутинам, они более традиционные в юнити, так что их в основном использую
Как раз тут вчера делал прыжок через корутины)) по заданию от препода, сделать там всякое без использования Update()
Хз че людям они не нравятся :D очень гибкий инструмент...
А можно теперь про многопоточность? :)
Спасибо, за видео, но у меня вопрос. Можно ли записать в куратину вот это -
Int a = 1, b = 1;
a + b;
?
Спасибо что смотрите :)
Да, всё что можно запихать в обычную функцию будет точно так же выполняться и в корутине
Не понял чем отличается if(vasya) yield return null отличается от if(vasya) return без всяких корутин
а у меня почему-то StopCoroutine(corName()) - не работает. попробовал создать экземпляр, с трудом корутина запустилась, но все равно метод остановки не работает, спасает только стополлкорутинс :"(
Давай про многопоточность
Привет! Я новичок, подскажите как сделать задержку после нажатия кнопки на экране (прыжок в данном случае) прежде чем смогу нажать ее повторно. Хочу попробовать таким методом убрать многократные прыжки (я знаю что есть и другие способы убрать многочисленный прыжок, но интересно можно ли этим способом так делать).
вы про Input GetButton ? надо что бы в каждом кадре не повторялось использовать или down или up , что бы еще меньше на моторику пальцев влияло (если не бить по клавише) лучше Up , те действие будет выполнено не только когда кнопка нажата но и отжата
Пожалуйста делай урок по Art Engine
А я тут использовал их для зацикливания или нажатия с паузой при нажатии кнопки UI
надоже, я думал я один ридером пользуюсь )
Приветствую друзья, может кто подскажет можно ли в рамках одного скрипта запустить респаун двух объектов, в разных точках и с разной задержкой респауна? если можно то как?
Основа корутинов - средство генерации анонимных итераторов в C# при помощи инструкции yield. Можно легко написать собственную реализацию корутинов при помощи этого языкового средства. Грустно, что подобный механизм не добавляют в Java - это ведь сильно расширяет возможности языка.
Да, yield это вещь мощная. Думал даже сделать видос про реализацию своих корутин, чтобы объяснить как они работают, но решил что это уже слишком будет)
В Java вообще ребята консервативные, не пойму как они без перегрузки операторов живут столько
@@EmeraldPowder добавить бы в Java перегрузку операторов и неуправляемые типы - был бы шикарный язык. Мне очень нравится, как в нём реализован механизм делегатов. Он универсальнее. От делегатов C# пахнет указателями на функции C++. В целом, в Java вполне можно реализовать что-то похожее на yield инструкции, только конструкция эта будет выглядеть не так элегантно, как в C#.
что делать? выдаёт ошибку - Assets\Scenes\scripts\courutine.cs(19,61): error CS0117: 'Quaternion' does not contain a definition for 'indentity'
(я совсем новичок в этом)
Правильно Quaternion.identity, советую пользоваться автодополнением в студии, тогда все эти названия не надо запоминать
@@EmeraldPowder спасибо, очень долго не мог понять что не то
thank you for video
Когда выключаешь скрипт на объекте (смена enabled) ты выключаешь только Update(), а остальные методы функционируют
Не только, но в целом именно так. Галка не отключает компонент, она всего лишь отключает несколько событий MonoBehaviour - docs.unity3d.com/ru/530/ScriptReference/MonoBehaviour.html.
а как передовать корутины между скриптами ?
Го урок по кулдауну
Так в чем преимущество этого метода, я не понял, если честно. К примеру, я могу написать всю логику в методе Update с счетчиком времени и всё.
Почему такую логику(со счетчиками) стоит выносить именно в корутины? просто для удобства и чтобы не заводить переменные для таймеров?
Иногда Update лучше подходит, но когда нужно сделать 5-10 непохожих действий с интервалом в пол секунды - то придётся делать либо 10 переменных таймеров, их инициализировать и следить за порядком. Либо делать enum с 10 значениями, большой switch, и один таймер. Но вообще технически всё что можно сделать корутинами - можно и через обычный апдейт
@@EmeraldPowder Понял, спасибо за ответ
Маленькая неточность. StopAllCoroutine останавливает только корутины, которые запущено от имени данного MonoBehaviour. Т.е. если на объекте их два, то корутины второго будут продолжать выполняться.
Да, спасибо за поправку, я как-то непонятно про это сказал. Там вот с привязкой то ли к объекту, то ли к компоненту, как раз много всяких неоднозначностей
В документации к StopAllCoroutines написано так: Note: StopAllCoroutines operates only on the one script it is attached to. Я проверял, можете проверить, так оно и работает ;). Вообще документация у Unity неплохая, часто находишь там то, что по началу пропускаешь по невнимательности. Так что всем советую внимательно ее изучать, и, конечно проводить эксперименты.
Ещё одна "фича" корутин в том что они классы и yield return new создаёт множество объектов которые сборщик мусора потом должен собрать. Поэтому желательно особенно в циклах сначала создавать один илд инструкцию и каждый раз возвращать один и тот же экземпляр инструкции.
Да, это их минус. Некоторые пытаются делать игры вообще без аллокаций, чтобы gc не влезал, тогда не подходят корутины. А так, если видишь в профайлере что сборщик много занимает, придётся постараться повыносить эти инструкции в локальные переменные, или заменить основные на yield return null, он вроде ничего не создаёт
@@EmeraldPowder я имею ввиду что если цикл и всегда фиксированный вейт, то написать сначала создание корутины и потом йелд одной и той же, не слишком сложно. Хотя конечно это уже оптимизация. Жаль, что только не упоминул в видео :)
Получается корутины работают асинхронно?
Как насчет сделать урок по инвентарю в играх?
КАКАЯ ЕЩЁ НАХЕР КОРУТИНА, КОРОУТАЙН ТАМ НАПИСАНО.
Забыл рассказать про использование в корутинах ключевого слова break ;)
корутины: существуют
люди: Thread.Sleep(TimeSpan.FromSeconds(5));
Часто использую вместо анимации, чтобы не добавлять аниматор везде где придется.
Я в юнити не шарю, и у меня вопрос больше к разрабам юнити.
Почему сделали это через yield, а не через async-await? Сделали бы что-то типа async Coroutine Coroutine() { await AnoterCoroutine();}
Насколько я знаю когда появлялись корутины в C# ещё не было async/await. А сейчас есть интерфейс для корутин с этими асинками, но мне кажется с yield выглядит проще
@@EmeraldPowder я нашёл либу UniTask - там корутины реализованы через async await (логика работы та же, даже все методы доступны). Лично мне такой подход нравится больше, тк IEnumerable и yield всё-таки изначально для коллекций создавались (и рекомендуется использовать именно для них, а не для кастомных стейт машин)
прощай invokeRepeating
Знаю про них с начала обучения, но ни разу не смог запустить. То одна, то другая проблема. Сейчас это "Не удается преобразовать из ...IEnumerable в string". И делай что хочешь. Превожу в стринг, так корутина даже не стартует
Хочу сказать по поводу паузы. Обычна она реализуется установкой Time.timeScale = 0, на что корутинам собственно все равно, они продолжают выполняться. Так что если хочешь чтобы паузы с корутинами работали корректно, приходится писать костыльные ифы. Если кто знает более нормальное решение, отпишитесь.
Смотря что в корутине делать. Если например спаун врагов раз в секунду - то юзаем WaitForSeconds, а не WaitForSecondsRealtime, то при остановке через timeScale всё будет корректно работать (на паузе спауна врагов не будет). А если движение например анимацией через какой-нибудь MoveTowards - то умножаем на Time.deltaTime, и он будет равен 0, если timeScale==0
Зачем они нужны когда есть DOTween?
(не считая асинхронных загрузок или примитивных веб-запросов)
а что в DOTWeen есть?
Все бы хорошо, но код плохо читается на темной теме.