Выуженастолькокруты,чтовертитекорутинамивокругвсехосейодновременно,отннооовашевзгл Простыеобертки—давнопройденныйэтап。
Вынастолькохорошоумеетеихготовить,чтомоглибыполучитьзвездуМишлена(атоиввевава)。 Конечно! Никтонеостанетсяравнодушным,отведаввашБуйабесскорутиннымсоусом。
Ужецелуюнеделюкодвпроденепадает! Обертки, callback
‘ииметоды Start/Stop Coroutine
程—уделхолопов。 Вамнужнобольшеконтроляисвободыдействий。 Выготовыподнятьсянаследующуюступеньку(нонеброситькорутины,конечно)。
Есливэтихстрокахвыузналисебя— —对кат。
Пользуясьслучаем,хочупередатьприветодномуизмоихлюбимыхпаттернов—命令。
Введение
Длявсехyieldинструкций,предоставляемыхUnity( Coroutine
, AsyncOperation
,WaiForSecondsидругие)базовымявляетсяничемнепримечас

Подкапотом,корутины—обычныеперечислители( IEnumerator
(docs))。 КаждыйкадрвызываетсяметодMoveNext MoveNext()
。 Есливозвращаемоезначениеравно true
-выполнениеоткладываетсядоследующего yield
оператора,есливе false
。
Длякастомных yield
инструкцийUnityпредоставляетодноименныйклассCustomYieldInstruction(文档)。

保持连接等待状态。 Егологикумыужеобсудиливыше。 true
Похпор,покакорутинадолжнавыполняться。
Примериздокументации:

Согласноейже,геттерkeepWatingвыполняетсякаждыйкадрпослеUpdate Update()
和LateUpdate()
。
Есливыработаетескодом,вкоторомопределенныевещидолжнысработатьвконкретный момент ,идосихпорнеизучиливотэту страницу – настоятельнорекомендуюрешитьсянасейподвиг。
Кастомныеyieldинструкции

关于CustomYieldInstruction
Номыжесвамисрадипришлинеочередныеобертки。 ЗатакоеможноибезМишленаостаться。
Потомукуримдальшедокументациюипрактическинадневсётойжестраницынаходимсамыйважный。
要拥有更多控制权并实现更复杂的收益指令,您可以直接从
System.Collections.IEnumerator
类继承。 在这种情况下,以与实现keepWaiting
属性相同的方式实现MoveNext()
方法。 除此之外,您还可以在Current
属性中返回一个对象,该对象将在执行MoveNext()
方法后由Unity的协程调度程序处理。 因此,例如,如果Current
返回了另一个继承自IEnumerator
对象,则当前枚举器将被挂起,直到返回的对象完成为止。
По-русски:
yieldтобыполучитьбольшеконтроляиреализоватьболеекомплексные
yield
инструкции,выможетенетенеледовать Вэтомслучае,реализуйтеметодMoveNextMoveNext()
,keepWaiting
。 Кромеэтого,выможетеиспользоватьобъектвсвойствеCurrent,которыйбудетобработанпланинононоо Например,еслисвойствоCurrent
возвращаетдругойобъектреализующийинтерфейсIEnumerator
,выполнениетекущегоперечислителябудетотложено,поканезавершитсявыполнениенового。
Святыемоллюски! ,тожетеконтрольисвободадействий,которыхтакхотелось。 Нувсё,теперьтовытаккорутинамизавертите,чтоникакойGimbal Lockнестрашен。 Главное,отсчастья,продсвертухинегрохнуть。
Интерфейс
,, Некийминимальныйнабор。
Предлагаюследующийвариант

请在IsExecuting
打折。 Есливыполнениекорутинынапаузе,以及всёещевыполняется。
Пасьянсикуртизанки
Какгласитдокументация,нужнореализоватьинтерфейсIEnumerator。 Внекоторыхместахпткачтоотавимзаглушки,

Стоитучитывать,чтокакминимумдваспособа,которыминашаинструкцияможетбытьзапущена:
- МетодStartCoroutine
StartCoroutine(IEnumerator routine)
:

2.Оператор yield
:

МетодExecute,IInstruction,КоторыймыописаливышевинтерфейсеIstruction,будетиспользоватьпервыйспособ。 Потомудобавимнесколькополей,которыепомогутуправлятьинструкциейвэтомслучае。

IInstruction
。

Также,методыдляобработкисобытийвдочернихклассах:

Онибудутвызыватьсявручнуюнепосредственнопередсоответствующимисобытиями,чтобытретин
Теперьоставшиесяметоды。

Здесьвсёпросто。 Инструкциюможнопоставитьнапаузутольковтомслучае,еслионавыполняетсяиеслиещёнеприостановлена,ипродолжитьвыполнение,толькоеслионоприостановлено。

ОсновнаялогикаостановкиинструкцийвынесенавметодStop。 Этонужнодлятого,чтобыиметьвозможностьвыполнитьтихуюостановку(безвызовасобытий)。
Проверка if (routine is Coroutine)
необходимапотому,что,какяписалвыше,инструкцияможетбытьзапущенаоператором yield
(тоестьбезвызова StartCoroutine
),азначитссылкинаконкретныйэкземпляр Coroutine
можетинеоказаться。 按照routine
будетлишьобъект-заглушка进行操作。

Основнойметодзапускатожекрайнепрост—запускбудетпроизведентольковтомслучаееслиин。
IEnumerator
,即IEnumerator
,可能是IEnumerator
,可能是IEnumerator
。

Исамоеинтересное,ноотэтогонеболеесложное,— MoveNext
:

if (!IsExecuting)
—启用StartCoroutine,并在yield中添加。 在routine
заглушкуивыстреливаемсобытиями中完成操作。
if (current != null)
— current
используетсядлядочернихинструкций。 Есливдругтакаяобъявилась,ждемееокончания。 Обратитевнимание,процессдобавленияподдержкидочернихинструкцийвэтойстатьеяупущу,чтобы。 Потому,еслидальнейшеедобавлениеданноцофункционалаваснеинтересует,можетепопростиубрать。
if (!Update())
—至少Update
CustomYieldInstructionидолжентерветер。 В Instruction
этопростоабстрактныйметод。

Код说明书целиком:

Вариантызапуска:

Примерызапуска:

Здесь,казалосьбы,всёмаксимальнопросто。 Вначалезаписаливремязапуска,以及потомпроверяемразницумеждутекущимвременемиStartTime。 Ноестьодиннюанс,которыйможносразуинезаметить。 Есливовремявыполненияинструкциивыприостановитееё(методомPause)иподождёте,топосоеоооонн Авсёпотому,чтосейчасэтаинструкциянеучитывает,чтоеомогупоставитьнапаузу。
Попробуемисправитьэтунесправедливость:

Готово。 Теперь,послеокончанияпаузы,инструкциябудетпродолжатьвыполнятьсястольковременисоое
Примерызапуска:
Итог
Unity上的Корутинывеливонувитвена。 Авотнасколькокомплекснымионибудутинужнылионивамвамвамвам。
Расширениефункционалакорутин—задачанесамаясложная。 Всё,чтовамнеобходимо,—решить,какойинтерфейсвзаимодействияснимивыхотитеиметь,икаки
Спасибозавашевремя。 Оставляйтесвоивопросы/замечания/дополнениявкомментариях。 Будурадобщению。
PSЕсли,внезапно,您вссподгорелопоповодуиспользованиякорутин,прочтитеэтоткоментатит