Unity中的自定义协程

Выуженастолькокруты,чтовертитекорутинамивокругвсехосейодновременно,отннооовашевзгл Простыеобертки—давнопройденныйэтап。

Вынастолькохорошоумеетеихготовить,чтомоглибыполучитьзвездуМишлена(атоиввевава)。 Конечно! Никтонеостанетсяравнодушным,отведаввашБуйабесскорутиннымсоусом。

Ужецелуюнеделюкодвпроденепадает! Обертки, callback ‘ииметоды Start/Stop Coroutine程—уделхолопов。 Вамнужнобольшеконтроляисвободыдействий。 Выготовыподнятьсянаследующуюступеньку(нонеброситькорутины,конечно)。

Есливэтихстрокахвыузналисебя— —对кат。

Пользуясьслучаем,хочупередатьприветодномуизмоихлюбимыхпаттернов—命令。

Введение

Длявсехyieldинструкций,предоставляемыхUnity( CoroutineAsyncOperation ,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 инструкции,выможетенетенеледовать Вэтомслучае,реализуйтеметодMoveNext MoveNext()keepWaiting 。 Кромеэтого,выможетеиспользоватьобъектвсвойствеCurrent,которыйбудетобработанпланинононоо Например,еслисвойство Current возвращаетдругойобъектреализующийинтерфейс IEnumerator ,выполнениетекущегоперечислителябудетотложено,поканезавершитсявыполнениенового。

Святыемоллюски! ,тожетеконтрольисвободадействий,которыхтакхотелось。 Нувсё,теперьтовытаккорутинамизавертите,чтоникакойGimbal Lockнестрашен。 Главное,отсчастья,продсвертухинегрохнуть。

Интерфейс

,, Некийминимальныйнабор。

Предлагаюс​​ледующийвариант

请在IsExecuting打折。 Есливыполнениекорутинынапаузе,以及всёеще​​выполняется。

Пасьянсикуртизанки

Какгласитдокументация,нужнореализоватьинтерфейсIEnumerator。 Внекоторыхместахпткачтоотавимзаглушки,

Стоитучитывать,чтокакминимумдваспособа,которыминашаинструкцияможетбытьзапущена:

  1. Метод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Если,внезапно,您вссподгорелопоповодуиспользованиякорутин,прочтитеэтоткоментатит