Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Game Development
  2. Unity
Gamedevelopment

Стварэнне дынамічных 2D вадзяных эфектаў у Unity

by
Difficulty:IntermediateLength:LongLanguages:

Belarusian (беларуская мова) translation by Alex Grigorovich (you can also view the original English article)

У гэтым уроку мы будзем мадэляваць дынамічнае 2D цела вады з дапамогай простай фізікі.  Мы будзем выкарыстоўваць сумесь лініі візуалізатара, сетка рэндэрыць, трыгеры і часціцы, каб стварыць наш эфект.  Канчатковы вынік пастаўляецца ў камплекце з хвалямі і пырскамі, гатовымі дадаць да наступнай гульні.  Адзінства (Unity3D) дэманстрацыйны крыніца уключаны, але вы павінны быць у стане ажыццявіць нешта падобнае, выкарыстоўваючы тыя ж прынцыпы, у любым гульнявым рухавічку.


канчатковы вынік

Вось тое, што мы збіраемся ў канчатковым выніку.  Вам спатрэбіцца убудова для браўзэра Unity, каб паспрабаваць яго.

Націсніце, каб стварыць новы аб'ект зваліцца ў ваду.

Настройка Наш менеджэр вады

У сваім падручніку, Майкл Хофман паказаў, як мы можам мадэляваць паверхню вады з шэрагам крыніц.

Мы будзем аказваць вяршыню нашай вады, выкарыстоўваючы адну з ліній рендереров Unity, і выкарыстоўваць столькі вузлоў, што яна з'яўляецца ў выглядзе бесперапыннай хвалі.

Create 2D Dynamic Water Effects in Unity Unity3D

Мы павінны сачыць за пазіцыямі, хуткасцяў і паскарэнняў кожнага вузла, хоць.  Каб зрабіць гэта, мы будзем выкарыстоўваць масівы.  Такім чынам, у верхняй часткі нашага класа мы дадамо гэтыя зменныя:

LineRenderer будзе захоўваць усе нашы вузлы і абмаляваць наша цела вады.  Нам усё яшчэ трэба саму ваду, хоць; мы створым гэта з Meshes. Мы будзем мець патрэбу ў аб'ектах, каб трымаць гэтыя сеткі таксама.

Мы таксама будзем мець патрэбу ў коллайдера, так што рэчы могуць ўзаемадзейнічаць з нашай вадой:

І мы будзем захоўваць усе нашы пастаянныя, а таксама:

Гэтыя канстанты такія ж, як Майкл абмяркоўвалася, за выключэннем z-гэта наш г-зрушэння для нашай вады.  Мы будзем выкарыстоўваць -1 для гэтага так, што яна будзе адлюстроўвацца перад нашымі аб'ектамі.  (Вы можаце змяніць гэта ў залежнасці ад таго, што вы хочаце, каб з'явіцца наперадзе і ззаду яго;. Вы збіраецеся павінны выкарыстоўваць Z-каардынаты, каб вызначыць, дзе спрайты сядзяць у адносінах да яго)

Далей, мы будзем трымацца на некаторыя значэння:

Далей, мы будзем трымацца на некаторыя значэння:

Гэта толькі памеры вады.Мы будзем мець патрэбу ў некаторых агульных зменных мы можам усталяваць у рэдактары, таксама.  Па-першае, сістэма часціц мы будзем выкарыстоўваць для нашых пырскаў:

Далей, матэрыял, які мы будзем выкарыстоўваць для нашай лініі візуалізатара (у выпадку, калі вы хочаце выкарыстоўваць сцэнар для кіслаты, лавы, хімічных рэчываў, або што-небудзь яшчэ):

Акрамя таго, выгляд сеткі мы будзем выкарыстоўваць для асноўнай масы вады:

Яны ўсе будуць заснаваныя на префабы, якія ўсё ўключаны ў зыходных файлах.

Мы хочам, каб аб'ект гульні, які можа ўтрымліваць ўсе гэтыя дадзеныя, выступаць у якасці мэнэджэра, і нерасту нашага цела вады Зброевай спецыфікацыі.  Каб зрабіць гэта, мы напішам функцыю, званую SpawnWater().

Гэтая функцыя будзе прымаць ўваходы з левага боку, шырыня, у верхняй частцы, а ў ніжняй часткі цела вады.

(Хоць гэта здаецца супярэчлівым, ён дзейнічае ў інтарэсах дызайну хуткага ўзроўню пры будаўніцтве злева направа).


Стварэнне вузлоў

Цяпер мы збіраемся, каб даведацца, колькі вузлоў нам трэба:

Мы збіраемся выкарыстаць пяць на адзінку шырыні, каб даць нам плыўнае рух, якое не занадта патрабавальныя.  (Вы можаце змяніць гэта, каб збалансаваць эфектыўнасць супраць гладкасці.)  Гэта дае нам усе нашы лініі, то нам трэба +1 для дадатковага вузла на канцы.

Першае, што мы збіраемся зрабіць, гэта робяць наша цела вадой з кампанентам LineRenderer:

Тое, што мы таксама зрабілі тут выбіраем наш матэрыял, і ўсталюеце яго, каб зрабіць над вадой, выбіраючы сваю пазіцыю ў чарзе рэндэрынгу.  Мы ўсталявалі правільнае лік вузлоў, і ўсталяваць шырыню лініі 0,1.

Вы можаце змяніць гэта ў залежнасці ад таго, якой таўшчыні вы хочаце, каб ваша лінія.  Вы, магчыма, заўважылі, што SetWidth() прымае два параметру; гэта шырыня ў пачатку і ў канцы лініі.  Мы хочам, каб шырыня быць пастаяннай.

Цяпер, калі мы зрабілі нашы вузлы, мы ініцыялізуючы ўсе нашы галоўныя зменныя:

Так што цяпер у нас ёсць усе нашы масівы, і мы праводзім па нашых дадзеных.

Цяпер на самай справе ўсталяваць значэнне нашых масіваў.  Мы пачнем з вузламі:

Тут мы ўсталёўваем усе у-пазіцыю, каб быць у верхняй частцы вады, а затым паступова дадаваць ўсе бакі вузлоў на баку.  Нашы хуткасці і паскарэння роўныя нулю на пачатковым этапе, а вада па-ранейшаму.

Мы завяршаем цыкл, усталёўваючы кожны вузел у нашым LineRenderer (Body) у правільнае становішча.


Стварэнне меш

Вось дзе яна становіцца складаней.

У нас ёсць лінія, але мы не маем саму ваду.  І тое, як мы можам зрабіць гэта з дапамогай мешей.  Мы пачнем з стварэння гэтых:

Цяпер, Сетка захоўваць кучу зменных.  Першы пераменны даволі проста: яна ня ўсе вяршыні (або куты).

Create 2D Dynamic Water Effects in Unity Unity3D

Дыяграма паказвае, што мы хочам, каб нашы сегменты сеткі выглядаць.  Для першага сегмента, вылучаныя вяршыні.  Мы хочам, усяго чатыры.

Цяпер, як вы можаце бачыць тут, вяршыня 0 з'яўляецца верхні левы, 1 верхні правы, 2 у ніжняй левай, і 3 у верхнім правым куце. Мы павінны памятаць, што для наступнага выкарыстання.

Другая ўласцівасць, якое зачэпліваецца патрэба ў UVs. Сеткі маюць тэкстуры, і UVs выбраць, якую частку тэкстуры мы хочам захапіць. У гэтым выпадку, мы проста хочам, каб верхні левы, верхні справа, унізе злева, і ніжні правы куты нашай тэкстуры. Сеткі маюць тэкстуры, і UVs выбраць, якую частку тэкстуры мы хочам захапіць.  У гэтым выпадку, мы проста хочам, каб верхні левы, верхні справа, унізе злева, і ніжні правы куты нашай тэкстуры.

Цяпер нам патрэбныя гэтыя лічбы з перш чым зноў.  Сеткі выкананы з трыкутнікаў, і мы ведаем, што любы чатырохкутнік можна зрабіць з двух трыкутнікаў, так што зараз мы павінны сказаць сетка, як гэта варта звярнуць гэтыя трыкутнікі.

Create 2D Dynamic Water Effects in Unity Unity3D

Паглядзіце на кутах з парадкам вузла з маркіроўкай. Трыкутніка A злучае вузлы 0, 1 і 3; Трохкутнік B злучае вузлы 3, 2 і 0. Такім чынам, мы хочам, каб зрабіць масіў, які змяшчае шэсць цэлых лікаў, які адлюстроўвае менавіта, што:

Гэта стварае наш чатырохкутнік.  Цяпер мы ўсталёўваем значэнне сеткі.

Цяпер у нас ёсць нашы Мешы, але ў нас няма гульнявых аб'ектаў, каб зрабіць іх у сцэне.  Такім чынам, мы збіраемся стварыць іх з нашага watermesh префаба, які змяшчае Mesh Renderer і сеткаваты фільтр.

Мы ўсталявалі сетку, і мы ўсталёўваем яго, каб быць дзіцем мэнэджара вады, каб давесці да ладу рэчы.


Стварэнне Нашы калізій

Цяпер мы хочам, каб наш коллайдер таксама:

Тут мы робім коллайдера скрынкі, даючы ім імя, каб яны трохі больш акуратнымі ў сцэне, і робім іх кожныя дзіця мэнэджара вады зноў.  Мы ўсталявалі сваё становішча, каб быць на паўшляху паміж вузламі, усталяваць іх памер і дадаць клас WaterDetector да іх.

Цяпер, калі ў нас ёсць сетка, нам патрэбна функцыя, каб абнавіць яго, як вада рухаецца:

Вы можаце заўважыць, што гэтая функцыя проста выкарыстоўвае код, які мы напісалі раней.  Адзінае адрозненне складаецца ў тым, што на гэты раз мы не павінны ўсталяваць трис- і UVs, таму што яны застаюцца тымі ж.

Наша наступная задача складаецца ў тым, каб вада сама праца.  Мы будзем выкарыстоўваць FixedUpdate (), каб змяніць іх усё паступова.


рэалізацыя Physics

Па-першае, мы збіраемся аб'яднаць закон Гук з метадам Эйлера, каб знайсці новыя пазіцыі, паскарэння і хуткасці.

Такім чынам, закон Гука \ (F = кх \), дзе \ (F \) з'яўляецца сіла, якая ствараецца спружынай (памятаеце, мы мадэлюючы паверхні вады ў выглядзе шэрагу крыніц), \ (да \) канстанта спружыны, і \ (х \) з'яўляецца зрушэнне.  Наша перасоўванне проста будзе у-становішча кожнага вузла за вылікам базавай вышыні вузлоў.

Далей, мы дадамо дэмпфіроўнымі множнік, прапарцыйны хуткасці сілы, каб аслабіць сілу.

Метад Эйлера просты; мы проста дадамо паскарэнне хуткасці і хуткасці ў становішча, кожны кадр.

Заўвага: Я толькі выказаў меркаванне, што маса кожнага вузла была 1, але вы будзеце выкарыстоўваць:

калі вы хочаце іншую масу для вашых вузлоў.

Савет: Для дакладнай фізікі, мы будзем выкарыстоўваць інтэграцыю Верлена, а таму, што мы дадаем дэмпфаванне, мы можам выкарыстоўваць толькі метад Эйлера, які нашмат хутчэй вылічыць.  У цэлым, аднак, метад Эйлера будзе экспанентна ўвесці кінэтычную энергію з ніадкуль у вашай сістэме фізікі, так што не выкарыстоўваць яго для чаго-небудзь дакладнага.

Цяпер мы збіраемся стварыць распаўсюджванне хваль.  Наступны код узяты з падручніка Майкла Хоффмана.

Тут мы ствараем два масіва.  Для кожнага вузла, мы збіраемся праверыць вышыню папярэдняга вузла ў адносінах да вышыні бягучага вузла і пакласці розніцу ў leftDeltas.

Затым мы праверым вышыню наступнага вузла з вышынёй вузла, якое мы правяраем, і паставіць гэтую розніцу ў rightDeltas.  (Мы таксама памножыць ўсе значэння на канстанту распаўсюджвання).

Мы можам змяніць хуткасці адразу на аснове рознасці вышынь, але мы павінны захоўваць толькі адрозненне ў пазіцыях ў гэтай кропцы.  Калі мы змянілі пазіцыю першага вузла прама з бітай, калі мы глядзелі на другім вузле, першы вузел ужо пераехаў, так што гэта разбурыць усе нашы разлікі.

Таму, як толькі мы сабралі ўсе нашы дадзеныя аб вышыні, мы можам прымяніць яго ў канцы.  Мы не можам глядзець справа ад вузла ў правай ці левай частцы вузла ў крайняе левае становішча, такім чынам, умовы i > 0 і i i < xpositions.Length - 1.

Акрамя таго, звярніце ўвагу, што мы ўтрымлівалі ўвесь гэты код у цыкле, і запусцілі яго ў восем разоў.  Гэта адбываецца таму, што мы хочам, каб запусціць гэты працэс у малых дозах часам некалькі, а не адзін вялікі разлік, які быў бы нашмат менш вадкасці.


даданне Пырскі

Цяпер у нас ёсць вада, якая цячэ, і гэта відаць.  Далей, мы павінны быць у стане парушыць ваду!

Для гэтага, давайце дадамо функцыю з імем Splash(), які будзе правяраць рэнтгенаўскае становішча ўсплёску, і хуткасць незалежна б'е яго.  Ён павінен быць публічным, так што мы можам назваць гэта з нашых коллайдером пазней.

Па-першае, мы павінны пераканацца, што паказаная пазіцыя на самай справе ў межах нашай вады:

І тады мы зменім xpos так гэта дае нам становішча адносна пачатку вадаёма:

Далей, мы збіраемся высветліць, які вузел гэта кранальна.  Можна падлічыць, што, як гэта:

Такім чынам, вось што адбываецца тут:

  1. Мы прымаем пазіцыю выплюхвання адносна пазіцыі левага краю вады (XPOS).
  2. Мы падзелім на пазіцыі правага краю адносна пазіцыі левага краю вады.
  3. Гэта дае нам доля, якая кажа нам, дзе ўсплёск.  Напрыклад, ўсплёск тры чвэрці шляху ўздоўж цела вады дасць значэнне 0,75.
  4. Мы памнажаем гэты лік рэбраў, і вакол гэтага ліку, што дае нам вузел нашаму ўсплёск быў бліжэй за ўсё да.

Цяпер мы ўсталёўваем хуткасць аб'екта, якія ўразілі нашу ваду на хуткасць гэтага вузла, так што ён атрымлівае запаволены аб'ектам.

Заўвага: Вы можаце змяніць гэты радок, што падыходзіць вам.  Напрыклад, вы маглі б дадаць хуткасць яго бягучай хуткасці, ці вы можаце выкарыстоўваць імпульс замест хуткасці і разрыву па масе вашага вузла.

Create 2D Dynamic Water Effects in Unity Unity3D

Цяпер мы хочам зрабіць сістэму часціц, якая будзе вырабляць фурор.  Мы вызначылі, што раней; гэта называецца «Усплёск» (досыць творча).  Будзьце ўпэўненыя, каб не блытаць яго з Splash().  Адзін я буду выкарыстоўваць уключаны ў зыходных файлах.

Па-першае, мы хочам, каб усталяваць параметры ўсплёску змяніць з хуткасцю аб'екта.

Тут мы ўзялі нашы часціцы, усталяваць тэрмін іх службы, каб яны не паміраюць неўзабаве пасля таго, як яны патрапілі на паверхню вады, і ўсталяваць іх хуткасць павінна быць заснавана на квадрат іх хуткасці (плюс канстанта, для маленькіх пырскаў) ,

Вы можаце глядзець на гэты код і думаць, «Чаму ён паставіў startSpeed двойчы?», І вы маеце рацыю здзіўляцца, што.  Праблема заключаецца ў тым, што мы выкарыстоўваем сістэму часціц (Shuriken, якая пастаўляецца з праектам), які мае сваю пачатковую хуткасць набору да «выпадковым паміж двума канстантамі».  На жаль, мы не маем дастатковай доступу над Shuriken з дапамогай скрыптоў, так, каб атрымаць такія паводзіны, каб працаваць, мы павінны ўсталяваць значэнне ў два разы.

Цяпер я збіраюся дадаць радок, вы можаце ці не можаце хацець выключыць з вашага сцэнара:

Часціцы Shuriken не будуць знішчаныя, калі яны трапяць на аб'екты, так што калі вы хочаце, каб пераканацца, што яны не збіраюцца на зямлю перад вашымі аб'ектамі, вы можаце прыняць дзве меры:

  1. Прытрымлівайцеся іх у фонавым рэжыме.  (Вы можаце сказаць гэта, г-становішчы будучы 5).
  2. Нахіліце сістэму часціц заўсёды накіраваны да цэнтра вашага цела вады-такім чынам, часціцы не выплюхнуць на зямлю.

Другая радок кода займае сярэднюю кропку пазіцыі, рухаецца уверх трохі, і паказвае на эмітар часціц ў адносінах да яго.  Я уключыў гэта паводзіны ў дэма.  Я уключыў гэта паводзіны ў дэма. Калі вы выкарыстоўваеце вельмі шырокі вадаём, вы, верагодна, не жадаеце гэтага.  Калі вада знаходзіцца ў невялікім басейне ўнутры пакоя, вы можаце захацець выкарыстоўваць яго.  Такім чынам, не саромейцеся адмовіцца ад гэтай лініі адносна кручэння.

Зараз, мы робім наш ўсплёск, і сказаць яму, каб памерці трохі пасля таго, як часціцы з-за смерці.  Чаму крыху пазней?  Паколькі наша сістэма часціц пасылае некалькі паслядоўных воплескаў часціц, так што нават калі першая партыя толькі апошні да жыцця Time.time + lifetime, нашы канчатковыя воплескі яшчэ будзе вакол трохі пасля гэтага.

Да! Мы нарэшце-то зрабілі, праўда?


выяўленне сутыкнення

Няправільна!  Нам трэба вызначыць нашы аб'екты, або ўсё гэта было дарма!

Памятаеце, мы дадалі, што сцэнар для ўсіх нашых коллайдером раней? Адзін называецца WaterDetector?

Ну мы збіраемся зрабіць гэта зараз!  Мы хочам толькі адну функцыю ў ім:

Выкарыстоўваючы OnTriggerEnter2D (), мы можам вызначыць, што адбываецца кожны раз, калі 2D цвёрдага цела ўваходзіць у наша цела вады.  Калі мы перадаем параметр Collider2D мы можам знайсці больш падрабязную інфармацыю аб гэтым аб'екце.

Мы хочам толькі тыя аб'екты, якія ўтрымліваюць rigidbody2D.

Зараз усе нашы коллайдера дзеці мэнэджара вады.  Такім чынам, мы проста захапіць кампанент Water ад іх бацькоў і выклікаць Splash(), з пазіцыі калайдэра.

Памятаеце, яшчэ раз, я сказаў, што вы можаце альбо перадаць хуткасць або імпульс, калі вы хочаце, каб гэта было фізічна больш дакладным?  Ну вось, дзе вы павінны прайсці правільны.  Калі памножыць у-хуткасць аб'екта па яго масе, вы будзеце мець свой імпульс.  Калі вы проста хочаце выкарыстоўваць сваю хуткасць, каб пазбавіцца ад масы ад гэтай лініі.

Нарэшце, вы хочаце патэлефанаваць SpawnWater () аднекуль.  Давайце рабіць гэта пры запуску:

А зараз мы зрабілі!  Зараз любы rigidbody2D з коллайдером, які трапіць у ваду стварае ўсплёск, і хвалі будуць рухацца правільна.

Create 2D Dynamic Water Effects in Unity Unity3D

бонус Практыкаванне

У якасці дадатковага бонуса, я дадаў некалькі радкоў кода ў верхняй частцы SpawnWater ().

Гэтыя радкі кода дадасць коллайдер скрынкі да самай вады.  Вы можаце выкарыстоўваць гэта, каб зрабіць рэчы усплываюць у вашай вадзе, выкарыстоўваючы тое, што вы даведаліся.

Вы хочаце, каб зрабіць функцыю, званую OnTriggerStay2D (), які прымае параметр Collider2D Hit.  Затым вы можаце выкарыстоўваць мадыфікаваную версію вясновай формулы мы выкарыстоўвалі да гэтага правярае масу аб'екта, і дадаць сілу або хуткасць да вашага rigidbody2D, каб зрабіць яго плаваць у вадзе.


Выклікаць сенсацыю

У гэтым уроку, мы рэалізавалі простую сімуляцыю вады для выкарыстання ў 2D-гульнях з простым кодам фізікі і лініяй візуалізатар, сеткамі рендерерами, трыгерамі і часціцамі.  Магчыма, вы будзеце дадаваць хвалістае цела вадкай вады як перашкода да наступнага платформер, гатовым для вашых персанажаў, каб паглыбіцца ў або старанна перасякацца з якія плаваюць камянямі крокавых, або, можа быць, вы маглі б выкарыстоўваць гэта ў паруснай або віндсерфінгу гульні, ці нават гульнях, дзе вы проста прапусціць скалы па вадзе ад сонечнага пляжу.  Поспехаў!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.