Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Unity
Gamedevelopment

Mewujudkan Kesan Air 2D Dinamik dalam Perpaduan

by
Difficulty:IntermediateLength:LongLanguages:

Malay (Melayu) translation by Meyria (you can also view the original English article)

Dalam tutorial ini, kita akan mensimulasikan badan 2D dinamik air menggunakan fizik mudah. Kami akan menggunakan campuran penghantar garis, penghasil mesh, pencetus dan zarah untuk menghasilkan kesan kami. Hasil akhir datang lengkap dengan gelombang dan percikan, bersedia untuk ditambahkan ke permainan berikutnya. Sumber demo Unity (Unity3D) dimasukkan, tetapi anda sepatutnya dapat melaksanakan sesuatu yang serupa dengan menggunakan prinsip yang sama dalam setiap enjin permainan.


Keputusan Akhir

Inilah apa yang akan kita jalani. Anda perlu plugin penyemak imbas Unity untuk mencubanya.

Klik untuk membuat objek baru untuk jatuh ke dalam air.

Menetapkan Pengurus Air Kita

Dalam tutorialnya, Michael Hoffman menunjukkan bagaimana kita dapat memodelkan permukaan air dengan berturut-turut mata air.

Kami akan menjadikan bahagian atas air kami menggunakan salah satu penunjuk garis Unity, dan menggunakan begitu banyak nod yang muncul sebagai gelombang berterusan.

Create 2D Dynamic Water Effects in Unity Unity3D

Kita perlu mengesan kedudukan, halaju dan percepatan setiap nod, walaupun. Untuk melakukan itu, kami akan menggunakan array. Jadi di bahagian atas kelas kami, kami akan menambah pembolehubah ini:

LineRenderer akan menyimpan semua nod kami dan menggariskan badan air kita. Kami masih memerlukan air itu sendiri, walaupun; kami akan membuatnya dengan Meshes. Kami akan memerlukan objek untuk memegang meshes ini juga.

Kami juga akan memerlukan penampung supaya perkara dapat berinteraksi dengan air kita:

Dan kami akan menyimpan semua pemalar kami juga:

Pemalar ini adalah jenis yang sama seperti dibincangkan Michael , dengan pengecualian z-ini adalah z-offset kami untuk air kami. Kami akan menggunakan -1 untuk ini supaya ia dipaparkan di hadapan objek kami. (Anda mungkin mahu mengubahnya bergantung kepada apa yang anda mahu muncul di depan dan belakangnya; anda perlu menggunakan koordinat z untuk menentukan tempat sprit duduk berbanding dengannya.)

Seterusnya, kami akan memegang beberapa nilai:

Ini hanyalah dimensi air.

Kita akan memerlukan beberapa pembolehubah awam yang boleh kita tetapkan dalam editor itu juga. Pertama, sistem zarah yang akan kita gunakan untuk percikan kita:

Seterusnya, bahan yang akan kami gunakan untuk penghantar baris kami (sekiranya anda mahu menggunakan semula skrip untuk asid, lava, bahan kimia, atau apa-apa lagi):

Tambahan pula, jenis mesh yang akan kita gunakan untuk badan utama air:

Ini semua akan didasarkan pada prefab, yang semuanya termasuk dalam fail sumber.

Kami mahukan objek permainan yang boleh memegang semua data ini, bertindak sebagai pengurus, dan menanam tubuh kita dalam ingame air untuk spesifikasi. Untuk melakukan itu, kami akan menulis fungsi yang dipanggil SpawnWater ().

Fungsi ini akan mengambil input dari sebelah kiri, lebar, bahagian atas, dan bahagian bawah badan air.

(Walaupun ini seolah-olah tidak konsisten, ia bertindak demi kepentingan reka bentuk tahap cepat apabila membina dari kiri ke kanan).


Membuat Nod

Sekarang kita akan mengetahui bilangan nod yang kita perlukan:

Kami akan menggunakan lima per unit lebar, untuk memberi kami gerakan lancar yang tidak terlalu menuntut. (Anda boleh mengubahnya untuk mengimbangi kecekapan terhadap kelancaran.) Ini memberikan kita semua baris, maka kita memerlukan +1 untuk nod tambahan pada akhirnya.

Perkara pertama yang akan kami lakukan ialah menjadikan badan air kami dengan komponen LineRenderer:

Apa yang telah kami lakukan di sini ialah pilih bahan kami, dan tetapkannya untuk meletakkan di atas air dengan memilih kedudukannya dalam baris gilir. Kami telah menetapkan bilangan nod yang betul, dan tetapkan lebar garisan kepada 0.1.

Anda boleh berbeza-beza bergantung pada betapa tebalnya anda mahu garis anda. Anda mungkin perasan bahawa SetWidth () mengambil dua parameter; ini adalah lebar pada permulaan dan akhir garisan. Kami mahu lebar itu menjadi berterusan.

Sekarang bahawa kami telah membuat nod kami, kami akan memulakan semua pembolehubah teratas kami:

Jadi sekarang kita mempunyai semua array kami, dan kami memegang data kami.

Kini sebenarnya untuk menetapkan nilai-nilai array kami. Kami akan mulakan dengan nod:

Di sini, kami menetapkan semua kedudukan y berada di bahagian atas air, dan kemudian secara bertahap menambah semua nod bersebelahan. Halaju dan pecutan kita adalah sifar pada mulanya, kerana air masih ada.

Kami menyelesaikan gelung dengan menetapkan setiap nod dalam LineRenderer (Badan) kami ke kedudukan yang betul mereka.


Mewujudkan Meshes

Di sinilah ia menjadi rumit.

Mari kita lihat dengan cepat contoh pelaksanaan ruang angkasa seperti dalam bahasa yang sama dengan C: Dan cara kita boleh membuat ini menggunakan Meshes. Kami akan mulakan dengan mencipta ini:

Sekarang, Meshes menyimpan sekumpulan pembolehubah. Pembolehubah pertama agak mudah: ia mengandungi semua simpang (atau sudut).

Create 2D Dynamic Water Effects in Unity Unity3D

Rajah menunjukkan apa yang kita mahu segmen jejaring kita kelihatan seperti. Untuk segmen pertama, simpul diserlahkan. Kami mahu empat keseluruhan.

Sekarang, seperti yang anda lihat di sini, puncak 0 adalah bahagian atas kiri, 1 adalah kanan atas, 2 adalah kiri-kiri, dan 3 adalah kanan atas. Kita perlu ingat bahawa untuk kemudian.

Harta kedua yang memerlukan adalah UVs. Meshes mempunyai tekstur, dan UVs memilih bahagian tekstur yang kita mahu ambil. Dalam kes ini, kita hanya mahu bahagian atas, kiri, kanan, bawah kiri, dan kanan bawah tekstur kita.

Sekarang kita memerlukan nombor-nombor itu dari sebelum lagi. Meshes terdiri daripada segitiga, dan kita tahu bahawa mana-mana segiempat boleh dibuat dari dua segitiga, jadi sekarang kita perlu memberitahu mesh bagaimana ia harus menarik segitiga itu.

Create 2D Dynamic Water Effects in Unity Unity3D

Lihat sudut-sudut dengan pesanan nod dilabel. Segitiga A menghubungkan nod 0, 1 dan 3; Segitiga B menghubungkan nod 3, 2 dan 0. Oleh itu, kami ingin membuat array yang mengandungi enam integer, yang mencerminkan dengan tepat bahawa:

Ini menjadikan segiempat kita. Sekarang kita menetapkan nilai mesh.

Sekarang, kami mempunyai jejaring kami, tetapi kami tidak mempunyai Objek Permainan untuk menjadikannya di tempat kejadian. Oleh itu, kami akan menciptanya dari prefab watermesh yang mengandungi Mesh Renderer dan Mesh Filter.

Kami menetapkan jejaring, dan kami menetapkannya untuk menjadi anak pengurus air, untuk membersihkannya.


Mewujudkan Perlanggaran Kami

Sekarang kita mahu kolider kita juga:

Di sini, kami membuat penjejak kotak, memberi nama kepada mereka supaya mereka sedikit tidier di tempat kejadian, dan menjadikan mereka setiap anak pengurus air lagi. Kami menetapkan kedudukan mereka untuk menjadi separuh antara nod, menetapkan saiz mereka, dan menambah kelas WaterDetector kepada mereka.

Sekarang bahawa kita mempunyai mesh kita, kita memerlukan fungsi untuk mengemas kini sebagai air bergerak:

Anda mungkin perasan bahawa fungsi ini hanya menggunakan kod yang kami tulis sebelum ini. Satu-satunya perbezaan adalah bahawa kali ini kita tidak perlu menetapkan tris dan UVs, kerana ini tetap sama.

Tugas kita seterusnya ialah membuat air itu berfungsi. Kami akan menggunakan FixedUpdate () untuk mengubah suai mereka semua secara berperingkat.


Melaksanakan Fizik

Mula-mula, kita akan menggabungkan Hooke's Law dengan kaedah Euler untuk mencari jawatan baru, pecutan dan halaju.

Oleh itu, Hukum Hooke adalah (F = kx ), di mana (F ) adalah daya yang dihasilkan oleh musim bunga (ingat, kami memodelkan permukaan air sebagai deretan mata air) adalah pemalar pegas, dan (x ) adalah anjakan. Anjakan kami semata-mata akan menjadi kedudukan y setiap nod minus ketinggian asas nod.

Seterusnya, kami menambah faktor redaman berkadar dengan halaju daya untuk melemahkan daya.

Kaedah Euler adalah mudah; kita hanya menambah pecutan ke halaju dan halaju ke kedudukan, setiap bingkai.

Nota: Saya hanya menganggap jisim setiap nod adalah 1 di sini, tetapi anda akan mahu menggunakan:

jika anda mahu jisim yang berbeza untuk nod anda.

Petua: Untuk fizik yang tepat, kita akan menggunakan integrasi Verlet, tetapi kerana kita menambah redaman, kita hanya boleh menggunakan kaedah Euler, yang lebih cepat untuk dikira. Secara umumnya, kaedah Euler secara eksponen akan memperkenalkan tenaga kinetik dari mana sahaja ke dalam sistem fizik anda, jadi jangan gunakannya untuk apa-apa yang tepat.

Sekarang kita akan membuat penyebaran gelombang. Kod berikut disesuaikan dengan tutorial Michael Hoffman.

Di sini, kami membuat dua baris. Untuk setiap nod, kita akan menyemak ketinggian nod sebelumnya terhadap ketinggian nod semasa dan meletakkan perbezaan ke kiriDeltas.

Kemudian, kami akan menyemak ketinggian nod seterusnya terhadap ketinggian nod yang kami semak, dan meletakkan perbezaan tersebut ke kananDeltas. (Kami juga akan membiak semua nilai dengan penyebaran berterusan).

Kita boleh mengubah halaju berdasarkan perbezaan ketinggian dengan serta-merta, tetapi kita hanya perlu menyimpan perbezaan dalam kedudukan pada ketika ini. Sekiranya kita menukar posisi nod pertama terus dari kelelawar, pada masa kita melihat nod kedua, nod pertama akan dipindahkan, sehingga akan merosakkan semua pengiraan kami.

Jadi sebaik sahaja kami mengumpul semua data ketinggian kami, kami boleh menggunakannya pada akhirnya. Kita tidak dapat melihat ke kanan nod di sebelah kanan, atau di sebelah kiri nod di sebelah kiri, maka syarat-syarat i> 0 dan i < xpositions.Length - 1.

Juga, perhatikan bahawa kami mengandungi kod ini dalam satu gelung, dan berlari lapan kali. Ini kerana kami ingin menjalankan proses ini dalam dos yang kecil beberapa kali, bukannya satu pengiraan yang besar, yang akan menjadi kurang banyak bendalir.


Menambah Splashes

Sekarang kita mempunyai air yang mengalir, dan ia menunjukkan. Seterusnya, kita perlu mengganggu air!

Untuk ini, mari tambahkan fungsi yang dipanggil Splash (), yang akan memeriksa kedudukan x percikan, dan halaju apa pun yang memukulnya. Ia harus awam supaya kita dapat memanggilnya dari pihak kami kemudian.

Pertama, kita perlu memastikan bahawa kedudukan yang ditentukan sebenarnya berada dalam batas air kita:

Dan kemudian kita akan menukar xpos sehingga memberikan kita kedudukan relatif kepada permulaan badan air:

Seterusnya, kami akan mengetahui nod yang menyentuh. Kita boleh mengira bahawa seperti ini:

Jadi, inilah yang berlaku di sini:

  1. Kami mengambil kedudukan percikan relatif terhadap kedudukan tepi kiri air (xpos).
  2. Kami membahagikan ini dengan kedudukan tepi kanan berbanding kedudukan tepi kiri air.
  3. Ini memberi kita pecahan yang memberitahu kita di mana percikan itu. Misalnya, percikan tiga perempat jalan di sepanjang badan air akan memberi nilai 0.75.
  4. Kami membiak ini dengan bilangan tepi dan pusingan nombor ini, yang memberi kami nod percikan kami paling dekat.

Sekarang kita menetapkan halaju objek yang melanda air kita ke halaju nod itu, supaya ia diseret oleh objek.

Nota: Anda boleh menukar baris ini kepada apa sahaja yang sesuai dengan anda. Sebagai contoh, anda boleh menambah halaju pada halaju semasa, atau anda boleh menggunakan momentum bukan halaju dan membahagikan massa massa anda.

Create 2D Dynamic Water Effects in Unity Unity3D

Sekarang kita mahu membuat sistem zarah yang akan menghasilkan percikan. Kami menetapkan bahawa sebelum ini; ia dipanggil ''splash'' (cukup kreatif). Pastikan anda tidak mengelirukan dengan Splash (). Yang saya akan gunakan termasuk dalam fail sumber.

Pertama, kami ingin menetapkan parameter percikan untuk berubah dengan halaju objek.

Di sini, kami telah mengambil zarah kami, menetapkan jangka hayat mereka supaya mereka tidak akan mati sejurus selepas mereka melanda permukaan air, dan menetapkan kelajuan mereka berdasarkan pada segi empat halaju mereka (ditambah dengan pemalar, untuk percikan kecil) .

Anda mungkin melihat kod itu dan berfikir, ''Kenapa dia menetapkan permulaanSpeed ​​dua kali?'', Dan anda betul-betul tertanya-tanya. Masalahnya ialah, kami menggunakan sistem zarah (Shuriken, yang disediakan dengan projek) yang mempunyai kelajuan permulaannya ditetapkan untuk ''rawak antara dua pemalar''. Malangnya, kita tidak mempunyai banyak akses ke atas Shuriken oleh skrip, jadi untuk mendapatkan tingkah laku itu berfungsi kita perlu menetapkan nilai dua kali.

Sekarang saya akan menambah garis yang anda mungkin atau mungkin tidak mahu meninggalkan skrip anda:

Zarah Shuriken tidak akan dimusnahkan apabila mereka memukul objek anda, jadi jika anda ingin memastikan mereka tidak akan mendarat di hadapan objek anda, anda boleh mengambil dua langkah:

  1. Lekatkan mereka di latar belakang. (Anda boleh memberitahu ini dengan kedudukan z ialah 5).
  2. Condongkan sistem zarah untuk sentiasa menunjuk ke arah pusat badan air anda-dengan cara ini, zarah-zarah tidak akan menyembur ke tanah.

Baris kedua kod mengambil titik tengah kedudukan, bergerak ke atas sedikit, dan menunjuk zarah pemancar ke arahnya. Saya telah memasukkan tingkah laku ini dalam demo. Sekiranya anda menggunakan air yang sangat luas, anda mungkin tidak mahu kelakuan ini. Jika air anda berada di dalam kolam kecil di dalam bilik, anda mungkin mahu menggunakannya. Jadi, jangan ragu untuk memotong garis tentang putaran.

Sekarang, kita membuat percikan kita, dan mengatakannya untuk mati sedikit setelah zarah-zarah itu mati. Mengapa sedikit selepas itu? Kerana sistem zarah kita mengeluarkan beberapa pecahan zarah berurutan, jadi walaupun batch pertama hanya bertahan hingga hayat Time.time + lifetime, letupan akhir kita akan tetap sedikit selepas itu.

Ya! Kami akhirnya selesai, bukan?


Pengesanan Perlanggaran

Salah! Kita perlu mengesan benda-benda kita, atau ini adalah untuk apa-apa!

Ingat, kami menambah skrip kepada semua pelaku kami sebelum ini? Yang dipanggil WaterDetector?

Nah, kita akan buat sekarang! Kami hanya mahukan satu fungsi di dalamnya:

Menggunakan OnTriggerEnter2D (), kami boleh menentukan apa yang berlaku apabila Tubuh 2D yang teguh memasuki badan kita. Sekiranya kita melewati satu parameter Collider2D kita dapat mencari lebih banyak maklumat mengenai objek tersebut.

Kami hanya mahu objek yang mengandungi rigidbody2D.

Sekarang, semua pelaku kami adalah anak-anak pengurus air. Jadi kita hanya ambil komponen Air dari ibu bapa mereka dan panggil Splash (), dari kedudukan collider.

Ingat sekali lagi, saya katakan anda boleh lulus halaju atau momentum, jika anda mahu ia lebih tepat dari segi fizikal? Nah, di sini anda perlu lulus yang betul. Jika anda membiak halaju y objek dengan jisimnya, anda akan mempunyai momentumnya. Jika anda hanya mahu menggunakan halajunya, hapuskan jisim dari garisan itu.

Akhir sekali, anda perlu memanggil SpawnWater () dari suatu tempat. Mari kita lakukan pada pelancaran:

Dan kini kami selesai! Sekarang mana-mana rigidbody2D  dengan collider yang mencecah air akan membuat percikan, dan gelombang akan bergerak dengan betul.

Create 2D Dynamic Water Effects in Unity Unity3D

Latihan Bonus

Sebagai bonus tambahan, saya telah menambah beberapa baris kod ke bahagian atas SpawnWater ().

Anda mungkin mempunyai beberapa idea anda sendiri sekarang. Jadi teruskan, cubalah mereka dan buat beberapa permainan! Anda boleh menggunakannya untuk membuat sesuatu terapung di dalam air anda, menggunakan apa yang anda pelajari.

Anda akan mahu membuat fungsi yang disebut OnTriggerStay2D () yang mengambil parameter Hit Collider2D. Kemudian, anda boleh menggunakan formula modul spring yang diubahsuai yang kami gunakan sebelum yang memeriksa jisim objek tersebut, dan menambah daya atau halaju kepada rigidbody2D anda untuk menjadikannya terapung di dalam air.


Buat Splash

Dalam tutorial ini, kami melaksanakan simulasi air sederhana untuk digunakan dalam permainan 2D dengan kod fizik yang mudah dan penghantar garis, penghasil mesh, pencetus dan zarah. Mungkin anda akan menambah badan cecair air cecair sebagai penghalang kepada platformer anda yang seterusnya, bersedia untuk watak anda menyelam atau berhati-hati menyeberangi batu melangkah melangkah, atau mungkin anda boleh menggunakannya dalam permainan pelayaran atau luncur angin, atau bahkan permainan di mana anda hanya melangkau batu melintasi air dari pantai yang cerah. Semoga berjaya!

Advertisement
Advertisement
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.