Menerapkan Path Finder untuk Agen AI dengan NavMesh

gambar

Mengikuti jalur dan mengendalikan lalu lintas


Terkadang kita membutuhkan karakter AI untuk berkeliaran di dunia game, mengikuti jalur yang ditentukan secara kasar atau ditentukan dengan tepat. Misalnya, dalam permainan balapan, lawan AI harus melakukan perjalanan di sepanjang jalan, dan di RTS, unit harus dapat bergerak ke titik yang diinginkan, bergerak di sepanjang medan dan memperhitungkan posisi masing-masing.

Agar tampak cerdas, agen AI harus dapat menentukan apa yang mereka lakukan, dan jika mereka tidak dapat mencapai titik yang diinginkan, maka mereka harus dapat merencanakan rute yang paling efektif dan mengubah jalur mereka ketika ada hambatan di jalan.

Menghindari rintangan adalah perilaku sederhana yang memungkinkan entitas AI mencapai titik target. Penting untuk dicatat bahwa perilaku yang diterapkan dalam posting ini adalah untuk perilaku seperti simulasi kerumunan, di mana tujuan utama setiap agen adalah untuk menghindari agen lain dan mencapai tujuan. Mereka tidak menentukan jalur yang paling efisien dan terpendek.

Persyaratan teknis


Membutuhkan Unity 2017 diinstal pada sistem dengan Windows 7 SP1 +, 8, 10, atau Mac OS X 10.9+. Kode dalam artikel ini tidak akan berfungsi pada Windows XP dan Vista, dan versi server Windows dan OS X belum diuji.

File kode untuk posting ini dapat ditemukan di GitHub .

Untuk mempelajari kode ini dalam aksi, tonton video ini .

Jala navigasi


Mari kita cari tahu cara menggunakan generator mesh navigasi Unity bawaan, yang dapat sangat menyederhanakan pencarian jalur untuk agen AI. Pada tahap awal Unity 5.x, fungsi NavMesh menjadi tersedia untuk semua pengguna, termasuk yang memiliki lisensi edisi pribadi, meskipun sebelumnya hanya berfungsi untuk Unity Pro. Sebelum rilis 2017.1, sistem telah diperbarui untuk menyediakan alur kerja berbasis komponen, tetapi karena membutuhkan paket tambahan yang dapat diunduh, yang pada saat penulisan ini hanya tersedia dalam versi pratinjau, kami akan mematuhi alur kerja berbasis adegan standar. Jangan khawatir, konsep kedua pendekatan itu serupa, dan ketika implementasi yang telah selesai akhirnya mencapai 2017.x, seharusnya tidak ada perubahan signifikan.

Pelajari lebih lanjut tentang sistem komponen NavMesh di Unity on GitHub .

Sekarang kita akan mengeksplorasi semua kemungkinan yang dapat ditawarkan oleh sistem ini kepada kita. Untuk mencari jalur AI, adegan harus disajikan dalam format tertentu; pada peta 2D, grid dua dimensi (array) digunakan untuk mencari jalur menggunakan algoritma A *. Agen AI perlu tahu di mana hambatannya, terutama yang statis. Berurusan dengan tabrakan antara objek yang bergerak secara dinamis adalah masalah lain yang biasa disebut sebagai perilaku kemudi. Unity memiliki alat bawaan untuk menghasilkan NavMesh, mewakili adegan dalam konteks yang nyaman bagi agen AI untuk menemukan jalur optimal ke target. Untuk memulai, buka proyek demo dan buka adegan NavMesh.

Kartu belajar


Setelah membuka adegan demo NavMesh, seharusnya terlihat seperti pada tangkapan layar:


Adegan hambatan dan kemiringan

Ini akan menjadi kotak pasir kami untuk menjelaskan dan menguji fungsionalitas sistem NavMesh. Skema umum mirip dengan game dalam genre RTS (strategi real-time). Kami mengendarai tangki biru. Klik pada titik yang berbeda sehingga tangki bergerak ke arah mereka. Indikator kuning adalah target tangki saat ini.

Navigasi statis


Pertama, Anda perlu mengatakan bahwa Anda harus menandai semua geometri dalam adegan, dipanggang di NavMesh, sebagai Navigasi Statis . Anda mungkin pernah melihat ini sebelumnya, misalnya, dalam sistem peta pencahayaan Unity. Untuk membuat objek game statis sangat sederhana, cukup centang kotak Statis untuk semua propertinya (navigasi, pencahayaan, culling, batching, dll.), Atau gunakan daftar drop-down untuk menentukan properti. Kotak centang terletak di sudut kanan atas inspektur objek yang dipilih.


Navigasi Properti Statis

Ini dapat dilakukan secara individual untuk objek yang berbeda atau, jika Anda memiliki hierarki objek game bawaan, terapkan parameter ke objek induk, setelah itu Unity akan menawarkan untuk menerapkannya ke semua objek anak.

Memanggang Mesh Navigasi


Untuk keseluruhan adegan, opsi navigasi navmesh diterapkan menggunakan jendela Navigasi . Jendela ini dapat dibuka dengan masuk ke Jendela | Navigasi Seperti jendela lainnya, jendela dapat diputus untuk gerakan bebas atau diperbaiki. Di tangkapan layar kami, ditampilkan sebagai tab merapat di sebelah hierarki, tetapi Anda dapat meletakkan jendela ini di tempat yang nyaman.

Membuka jendela, Anda akan melihat tab individual. Akan terlihat seperti ini:


Jendela Navigasi

Dalam kasus kami, tangkapan layar sebelumnya menunjukkan tab Bake , tetapi di editor Anda, tab apa pun dapat dipilih secara default.

Mari kita lihat masing-masing tab, mulai dari kiri dan pindah ke kanan. Mari kita mulai dengan tab Agen , yang terlihat seperti tangkapan layar menunjukkan:


Tab Agen

Jika Anda mengerjakan proyek lain, Anda mungkin menemukan bahwa beberapa pengaturan berbeda dari yang kami atur untuk proyek contoh yang ditunjukkan pada tangkapan layar. Di bagian atas tab ada daftar di mana Anda dapat menambahkan jenis agen baru dengan mengklik tombol + . Anda dapat menghapus agen tambahan dengan memilihnya dan mengklik tombol - . Jendela dengan jelas menunjukkan apa yang dilakukan berbagai pengaturan saat mengubahnya. Mari kita lihat apa yang dilakukan masing-masing pengaturan:

  • Nama: nama jenis agen yang ditampilkan dalam daftar turun-bawah Jenis Agen.
  • Radius: Anda dapat menganggapnya sebagai "ruang pribadi" agen. Agen akan mencoba untuk menghindari kontak yang terlalu dekat dengan agen lain berdasarkan nilai ini, karena digunakan dalam penghindaran.
  • Tinggi: seperti yang Anda duga, pengaturan ini menetapkan ketinggian agen yang digunakannya untuk penghindaran vertikal (misalnya, ketika melewati benda-benda di bawah).
  • Tinggi Langkah: nilai ini menentukan ketinggian apa yang bisa dipanjat agen.
  • Max Slope: seperti yang akan kita lihat dari bagian selanjutnya, nilai ini menentukan sudut maksimum di mana agen dapat naik. Dengan menggunakan parameter ini, Anda dapat membuat lereng curam peta tidak dapat diakses oleh agen.

Selanjutnya, kami memiliki tab Area , yang terlihat seperti yang ditunjukkan pada tangkapan layar ini:


Seperti yang dapat Anda lihat di tangkapan layar, Unity menyediakan beberapa jenis area yang tidak dapat diubah: Walkable , Not Walkable, dan Jump . Selain memberi nama dan membuat area baru, Anda dapat menetapkan biaya untuk bergerak di area tersebut.

Area melayani dua tujuan: membuat area dapat diakses atau tidak dapat diakses oleh agen, dan menandai area yang kurang diinginkan dalam hal biaya perjalanan. Misalnya, Anda dapat mengembangkan RPG di mana musuh iblis tidak dapat memasuki area yang ditandai sebagai "tanah yang dikuduskan". Anda juga dapat menandai beberapa area peta sebagai "rawa" atau "rawa", yang akan dihindari agen karena tingginya biaya bergerak.

Tab Panggang ketiga mungkin yang paling penting. Ini memungkinkan Anda untuk membuat NavMesh sendiri untuk adegan itu. Anda harus sudah terbiasa dengan beberapa opsi. Tab Bake terlihat seperti ini:


Bake tab

Opsi ukuran agen pada tab ini menentukan bagaimana agen akan berinteraksi dengan lingkungan, sedangkan opsi pada tab Agen mengontrol interaksi dengan agen lain dan objek bergerak. Tetapi mereka mengontrol parameter yang sama, jadi kita akan melewatkannya. Jatuhkan Tinggi dan Jarak Lompat mengontrol seberapa jauh agen dapat "melompat" untuk mencapai bagian NavMesh yang tidak terkait langsung dengan bagian di mana agen saat ini berada. Kami akan mempertimbangkan ini secara lebih rinci di bawah ini, jadi jika Anda tidak yakin, maka Anda masih tidak dapat mempelajari parameter ini.

Selain itu, ada opsi lanjutan yang biasanya disembunyikan secara default. Untuk memperluas opsi ini, cukup klik pada segitiga tarik-turun di sebelah tajuk Tingkat Lanjut . Ukuran Manual Voxel dapat dianggap sebagai pengaturan "kualitas". Semakin kecil ukurannya, semakin banyak detail yang akan disimpan dalam jaring. Area Wilayah Min digunakan untuk melewati platform pemanggangan atau permukaan di bawah ambang batas yang dipilih. Tinggi Mesh memberi kita data vertikal yang lebih rinci saat memanggang mesh. Misalnya, opsi ini memungkinkan Anda untuk mempertahankan lokasi agen yang benar saat menaiki tangga.

Tombol Hapus menghapus semua data NavMesh dari adegan tersebut, dan tombol Bake menciptakan mesh untuk adegan tersebut. Proses memanggang cukup cepat. Selama Anda memiliki jendela yang dipilih, Anda dapat mengamati generasi NavMesh dengan tombol Bake di jendela adegan. Mari klik tombol Bake untuk melihat hasilnya. Dalam contoh adegan kami, kami berakhir dengan sesuatu yang mirip dengan tangkapan layar ini:


Area biru menunjukkan NavMesh. Di bawah ini kami akan kembali ke sini. Sementara itu, mari kita beralih ke tab terakhir - Obyek , yang terlihat seperti ini:


Tiga tombol yang diperlihatkan dalam tangkapan layar sebelumnya - All , Mesh Renderers, dan Terrains - digunakan sebagai filter adegan. Mereka berguna saat bekerja dalam adegan kompleks dengan banyak objek dalam hierarki. Memilih opsi memfilter jenis yang sesuai dari hierarki, membuatnya mudah untuk memilihnya. Anda dapat menggunakan tombol untuk menjelajahi adegan Anda dalam mencari objek yang ingin Anda tandai sebagai navigasi statis.

Menggunakan Agen Nav Mesh


Sekarang kami telah menyiapkan adegan dengan NavMesh, kami membutuhkan cara bagi agen untuk menggunakan informasi ini. Untungnya bagi kami, Unity memiliki komponen Nav Mesh Agent yang dapat Anda seret ke karakter. Dalam adegan contoh kami, ada objek permainan yang disebut Tank , yang komponennya sudah terpasang. Lihatlah hierarki dan Anda akan melihat sesuatu seperti ini:


Ada beberapa parameter di sini, dan kami tidak akan mempertimbangkan semuanya, karena cukup jelas, dan uraiannya dapat ditemukan di dokumentasi resmi Unity. Tetapi kami akan menyebutkan hal-hal utama:

  • Jenis Agen : Ingat tab Agen di jendela Navigasi ? Jenis agen yang dapat ditugaskan dapat dipilih di sini.
  • Auto Traverse Off Mesh Link : Opsi ini memungkinkan agen untuk secara otomatis menggunakan fitur Off Mesh Links , yang akan kita bahas di bawah ini.
  • Area Mask : di sini Anda dapat memilih area yang dikonfigurasikan di tab Area pada jendela Navigasi .

Itu saja. Komponen ini melakukan 90% kerja keras untuk kita: membuka jalan, menghindari rintangan, dan sebagainya. Satu-satunya hal yang Anda butuhkan adalah mentransfer titik target ke agen. Mari kita lihat masalah ini.

Pengaturan Titik Target


Setelah mengatur agen AI, kita perlu cara untuk memberitahunya ke mana harus pergi. Dalam proyek contoh kami, ada skrip bernama Target.cs yang melakukan tugas ini dengan tepat.

Ini adalah kelas sederhana yang melakukan tiga hal:

  • “Tembak” pancaran dari kamera ke posisi mouse di dunia
  • Memperbarui posisi marker
  • Memperbarui properti tujuan untuk semua agen NavMesh.

Kode ini cukup sederhana. Seluruh kelas adalah sebagai berikut:

using UnityEngine; using UnityEngine.AI; public class Target : MonoBehaviour { private NavMeshAgent[] navAgents; public Transform targetMarker; private void Start () { navAgents = FindObjectsOfType(typeof(NavMeshAgent)) as NavMeshAgent[]; } private void UpdateTargets ( Vector3 targetPosition ) { foreach(NavMeshAgent agent in navAgents) { agent.destination = targetPosition; } } private void Update () { if(GetInput()) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hitInfo; if (Physics.Raycast(ray.origin, ray.direction, out hitInfo)) { Vector3 targetPosition = hitInfo.point; UpdateTargets(targetPosition); targetMarker.position = targetPosition; } } } private bool GetInput() { if (Input.GetMouseButtonDown(0)) { return true; } return false; } private void OnDrawGizmos() { Debug.DrawLine(targetMarker.position, targetMarker.position + Vector3.up * 5, Color.red); } } 

Tindakan berikut terjadi di sini: di metode Mulai , kami menginisialisasi array navAgents menggunakan metode FindObjectsOfType () .

Metode UpdateTarget () melewati array navAgents kami dan menetapkan titik target untuk mereka dalam Vector3 yang diberikan. Ini adalah kunci kode. Anda dapat menggunakan mekanisme apa pun untuk mendapatkan titik target, dan agar agen pindah ke sana, cukup setel bidang NavMeshAgent.destination ; agen akan melakukan sisanya.

Dalam contoh kami, klik digunakan untuk bergerak, jadi ketika pemain mengklik mouse, kami melepaskan sinar dari kamera ke dunia ke arah kursor mouse, dan jika berpotongan dengan sesuatu, maka kami menetapkan titik tumbukan ke agen targetPosisi yang baru. Kami juga menyesuaikan penanda target sesuai dengan mudah memvisualisasikan tujuan dalam permainan.

Untuk menguji operasi, Anda perlu memanggang NavMesh sesuai dengan deskripsi dari bagian sebelumnya, lalu mulai mode Putar dan pilih area mana saja di peta. Jika Anda mengklik berkali-kali, Anda dapat melihat bahwa agen tidak dapat mencapai beberapa area - bagian atas kubus merah, platform atas dan platform di bagian bawah layar.

Kubus merah terlalu tinggi. Kemiringan yang mengarah ke platform tertinggi terlalu tajam untuk pengaturan Max Slope kami, dan agen tidak dapat memanjatnya. Tangkapan layar berikut menunjukkan bagaimana pengaturan Max Slope memengaruhi NavMesh:


NavMesh dengan kemiringan maks = 45

Jika Anda mengubah nilai Max Slope ke sesuatu seperti 51 , dan kemudian klik tombol Bake lagi untuk memanggang NavMesh lagi, hasilnya adalah sebagai berikut:


NavMesh dengan kemiringan maksimum = 51

Seperti yang Anda lihat, kami dapat menyesuaikan desain level, membuat seluruh area tidak dapat diakses dengan mengubah satu parameter. Ini bisa berguna, misalnya, ketika Anda memiliki platform atau langkan yang membutuhkan tali, tangga atau lift untuk dipanjat. Atau mungkin keterampilan khusus, misalnya, kemampuan memanjat?

Aplikasi Off Mesh Links


Anda mungkin memperhatikan bahwa ada dua jeda di adegan kami. Agen kami dapat masuk ke yang pertama, tetapi yang di bagian bawah layar terlalu jauh. Perhitungan ini tidak sepenuhnya arbitrer. Off Mesh Links pada dasarnya membuat jembatan melintasi ruang antara segmen NavMesh yang tidak terkait. Tautan ini dapat dilihat di editor:


Lingkaran biru dengan garis penghubung adalah koneksi.

Unity dapat menghasilkan tautan ini dalam dua cara. Yang pertama sudah kami pertimbangkan. Ingat nilai Jump Distance di tab Bake pada jendela Navigasi ? Unity secara otomatis menggunakan nilai itu untuk menghasilkan tautan ini saat memanggang NavMesh. Coba ubah nilainya di adegan pengujian kami menjadi 5 dan buat lagi. Lihat - platform sekarang terhubung? Ini karena jerat sekarang dalam ambang yang ditentukan baru.

Ubah nilainya menjadi 2 lagi dan panggang. Sekarang mari kita lihat cara kedua. Buat bola yang akan digunakan untuk menghubungkan kedua platform. Tempatkan kira-kira seperti yang ditunjukkan pada tangkapan layar:


Anda sudah dapat melihat apa yang terjadi, tetapi mari kita menganalisis proses yang memungkinkan mereka terhubung. Dalam kasus kami, saya menyebut bola di awal yang benar, dan bola di ujung kiri. Anda akan segera mengerti mengapa. Selanjutnya, saya menambahkan komponen Off Mesh Link ke platform di sebelah kanan (relatif terhadap tangkapan layar sebelumnya). Anda akan melihat bahwa komponen memiliki bidang awal dan akhir . Seperti yang Anda tebak, kami akan menyeret bola yang dibuat sebelumnya ke slot yang sesuai - bola awal di bidang awal dan bola akhir di bidang akhir . Inspektur akan terlihat seperti ini:


Nilai Override Biaya diperhitungkan saat diberi nilai positif. Ini menerapkan faktor biaya ketika menggunakan hubungan ini sebagai lawan dari rute yang lebih hemat biaya ke target.

Bi Directional jika benar memungkinkan agen bergerak ke dua arah. Untuk membuat tautan dengan lalu lintas satu arah, Anda dapat menonaktifkan nilai ini. Nilai Activated digunakan sesuai dengan namanya. Jika salah, agen mengabaikan hubungan ini. Anda dapat menghidupkan dan mematikannya untuk membuat skenario permainan di mana, misalnya, pemain harus menekan sakelar untuk mengaktifkan koneksi.

Untuk mengaktifkan hubungan ini, memanggang ulang tidak diperlukan. Lihatlah NavMesh Anda dan Anda akan melihat bahwa tampilannya persis seperti pada tangkapan layar:


Seperti yang Anda lihat, celah yang lebih kecil masih terhubung secara otomatis, dan sekarang kami memiliki koneksi baru yang dihasilkan oleh komponen Off Mesh Link antara dua bola. Luncurkan mode Putar dan klik pada platform jauh. Seperti yang diharapkan, agen sekarang dapat menavigasi ke platform terputus:


Di level gim Anda, Anda mungkin perlu mengubah parameter ini untuk mencapai hasil yang diinginkan, tetapi kombinasi fitur-fitur ini memberi Anda alat yang nyaman dan siap pakai. Anda dapat dengan cepat membuat game sederhana menggunakan fungsionalitas NavMesh.

Tutorial ini adalah bagian dari Pemrograman AI Game Unity 2017 - Edisi Ketiga oleh Ray Barrera, Aung Sithu Kyaw dan Thet Naing Swe.

Source: https://habr.com/ru/post/id414453/


All Articles