Catatan : tutorial ini ditujukan untuk pengguna mahir dan berpengalaman, dan tidak mencakup topik seperti menambahkan komponen, membuat skrip GameObject baru, dan sintaksis C #. Jika Anda perlu meningkatkan keterampilan Unity Anda, lihat tutorial Memulai Penggunaan dengan Unity dan Pengantar Script Unity kami .
Di bagian
pertama tutorial, kami belajar cara membuat kait kucing dengan mekanisme melilitkan tali di sekeliling rintangan. Namun, kami ingin lebih: tali dapat membungkus benda di tingkat, tetapi tidak lepas ketika Anda kembali.
Mulai bekerja
Buka proyek jadi dari bagian pertama di Unity atau unduh
draf untuk bagian tutorial ini, lalu buka
2DGrapplingHook-Part2-Starter . Seperti pada bagian pertama, kita akan menggunakan versi Unity 2017.1 atau lebih tinggi.
Buka adegan
Game di editor dari folder proyek
Scenes .
Luncurkan adegan Game dan coba kaitkan kait kucing di atas batu di atas karakter, lalu ayun untuk membuat tali membungkus sepasang tepi batu.
Ketika Anda kembali, Anda akan melihat bahwa titik-titik batu tempat tali yang digunakan untuk berbalik tidak terlepas lagi.
Pikirkan tentang titik di mana tali harus dibuka. Untuk menyederhanakan tugas, lebih baik menggunakan kasing saat tali membungkus ujung-ujungnya.
Jika siput, menempel pada batu di atas kepalanya, berayun ke kanan, maka tali akan bengkok setelah ambang batas di mana ia melintasi titik sudut 180 derajat dengan tepi yang saat siput terpasang. Pada gambar di bawah, ini ditunjukkan oleh titik hijau yang disorot.
Ketika siput itu berayun kembali ke arah lain, tali itu harus kembali terlepas pada titik yang sama (disorot dengan warna merah pada gambar di atas):
Logika tidak terputus-putus
Untuk menghitung momen ketika Anda perlu melepas tali pada titik-titik yang dibungkus sebelumnya, kita perlu pengetahuan tentang geometri. Secara khusus, kami akan menggunakan perbandingan sudut untuk menentukan kapan tali harus dilepas dari tepi.
Tugas ini mungkin tampak sedikit mengintimidasi. Matematika dapat menginspirasi horor dan keputusasaan bahkan dalam yang paling berani.
Untungnya, Unity memiliki beberapa fungsi penolong matematika yang hebat yang dapat membuat hidup kita sedikit lebih mudah.
Buka skrip
RopeSystem di IDE dan buat metode baru yang disebut
HandleRopeUnwrap()
.
private void HandleRopeUnwrap() { }
Buka
Update()
dan tambahkan pada akhirnya panggilan ke metode baru kami.
HandleRopeUnwrap();
Sementara
HandleRopeUnwrap()
tidak melakukan apa-apa, tetapi sekarang kita dapat memproses logika yang terkait dengan seluruh proses melepaskan dari tepi.
Seperti yang Anda ingat dari bagian pertama tutorial, kami menyimpan posisi pembungkus tali dalam koleksi yang disebut
ropePositions
, yang merupakan koleksi
List<Vector2>
. Setiap kali tali melilit ujung, kami menjaga posisi titik bungkus ini dalam koleksi ini.
Untuk membuat proses lebih efisien, kami tidak akan menjalankan logika apa pun di
HandleRopeUnwrap()
jika jumlah posisi yang disimpan dalam koleksi sama dengan atau kurang dari 1.
Dengan kata lain, ketika siput telah terhubung ke titik awal dan tali belum melilit ujungnya, jumlah
ropePositions
adalah 1, dan kami tidak akan mengikuti logika pemrosesan yang tidak diputar.
Tambahkan
return
sederhana ini ke bagian atas
HandleRopeUnwrap()
untuk menghemat siklus CPU yang berharga, karena metode ini dipanggil dari
Update()
berkali-kali per detik.
if (ropePositions.Count <= 1) { return; }
Menambahkan Variabel Baru
Di bawah pengujian baru ini, kami akan menambahkan beberapa dimensi dan referensi ke berbagai sudut yang diperlukan untuk menerapkan dasar dari logika yang tidak terputar. Tambahkan kode berikut ke
HandleRopeUnwrap()
:
Ada banyak variabel di sini, jadi saya akan menjelaskan masing-masing, serta menambahkan ilustrasi yang nyaman yang akan membantu untuk memahami tujuan mereka.
anchorIndex
adalah indeks dalam koleksi ropePositions
di dua posisi dari akhir koleksi. Kita dapat menganggapnya sebagai titik di dua posisi pada tali dari posisi siput. Pada gambar di bawah ini, ini adalah titik pertama pengait kait ke permukaan. Saat mengisi koleksi ropePositions
titik pembungkus baru, titik ini akan selalu tetap menjadi titik pembungkus pada jarak dua posisi dari siput.hingeIndex
adalah indeks koleksi yang menyimpan titik engsel saat ini; dengan kata lain, posisi tali saat ini sedang membungkus titik terdekat dengan ujung tali dari siput. Itu selalu pada jarak satu posisi dari siput, itulah sebabnya kami menggunakan ropePositions.Count - 1
.anchorPosition
dihitung dengan merujuk tempat ropePositions
koleksi ropePositions
dan merupakan nilai Vector2 sederhana dari posisi itu.hingePosition
dihitung dengan merujuk tempat hingeIndex
dalam koleksi ropePositions
dan merupakan nilai Vector2 sederhana dari posisi itu.hingeDir
adalah vektor yang diarahkan dari anchorPosition
ke hingePosition
. Ini digunakan dalam variabel berikut untuk mendapatkan sudut.hingeAngle
- fungsi pembantu yang berguna Vector2.Angle()
digunakan di sini untuk menghitung sudut antara anchorPosition
dan titik engsel.playerDir
adalah vektor yang diarahkan dari anchorPosition
ke posisi siput saat ini (playerPosition)- Kemudian, menggunakan sudut antara titik jangkar dan pemain (siput),
playerAngle
dihitung.

Semua variabel ini dihitung menggunakan posisi yang disimpan sebagai nilai Vector2 dalam koleksi
ropePositions
dan membandingkan posisi ini dengan posisi lain atau posisi pemain saat ini (slug).
Dua variabel penting yang digunakan untuk perbandingan adalah
hingeAngle
dan
playerAngle
.
Nilai yang disimpan dalam
hingeAngle
harus tetap statis karena selalu sudut yang konstan antara titik di dua "lipatan tali" dari siput dan "lipatan tali" saat ini yang paling dekat dengan siput yang tidak bergerak sampai tali tidak terpilin atau setelah dilipat titik tikungan baru akan ditambahkan.
Saat siput
playerAngle
berubah. Dengan membandingkan sudut ini dengan
hingeAngle
, dan juga memeriksa apakah siput di sebelah kiri atau kanan sudut ini, kita dapat menentukan apakah titik lipat saat ini yang paling dekat dengan siput harus dilepaskan.
Di bagian pertama tutorial ini, kami menyimpan posisi lipatan dalam kamus yang disebut
wrapPointsLookup
. Setiap kali kami menyimpan titik tekuk, kami menambahkannya ke kamus dengan posisi sebagai kunci dan dengan 0 sebagai nilainya. Namun, nilai 0 ini agak misterius, bukan?
Kami akan menggunakan nilai ini untuk menyimpan posisi siput relatif terhadap sudutnya dengan titik engsel (titik lipat saat ini paling dekat dengan siput).
Jika Anda menetapkan nilai
-1 , maka sudut siput (
playerAngle
) kurang dari sudut engsel (
hingeAngle
), dan dengan nilai
1, sudut
playerAngle
lebih besar daripada
hingeAngle
.
Karena fakta bahwa kita menyimpan nilai-nilai dalam kamus, setiap kali kita membandingkan
playerAngle
dengan
hingeAngle
, kita dapat memahami apakah siput baru saja melewati batas yang setelah itu tali harus dilepas.
Ini dapat dijelaskan secara berbeda: jika sudut siput baru saja diperiksa dan lebih kecil dari sudut engsel, tetapi terakhir kali disimpan dalam kamus titik lengkung itu ditandai dengan nilai yang menunjukkan bahwa itu berada di sisi lain sudut ini, maka titik tersebut harus dihapus !
Tali pemisah
Lihatlah screenshot di bawah ini dengan catatan. Siput kami menempel di batu, bergoyang ke atas, melilitkan tali di tepi batu pada saat naik.
Anda mungkin memperhatikan bahwa pada posisi ayunan paling atas, di mana siputnya buram, titik lipatan terdekat saat ini (ditandai dengan titik putih) akan disimpan dalam kamus
wrapPointsLookup
dengan nilai
1 .
Dalam perjalanan turun, ketika
playerAngle
menjadi lebih kecil daripada
hingeAngle
(dua garis hijau putus-putus), seperti yang ditunjukkan oleh panah biru, pemeriksaan dilakukan, dan jika nilai terakhir (saat ini) dari titik bengkok adalah
1 , maka titik bengkok harus dihapus.
Sekarang mari kita terapkan logika ini dalam kode. Tetapi sebelum kita mulai, mari kita buat metode kosong yang akan kita gunakan untuk bersantai. Karena ini, setelah membuat logika, itu tidak akan menyebabkan kesalahan.
Tambahkan metode
UnwrapRopePosition(anchorIndex, hingeIndex)
baru
UnwrapRopePosition(anchorIndex, hingeIndex)
dengan memasukkan baris berikut:
private void UnwrapRopePosition(int anchorIndex, int hingeIndex) { }
Setelah melakukan ini, kembali ke
HandleRopeUnwrap()
. Di bawah variabel yang baru ditambahkan, tambahkan logika berikut, yang akan menangani dua kasus:
playerAngle
kurang dari
hingeAngle
dan
playerAngle
lebih dari
hingeAngle
:
if (playerAngle < hingeAngle) {
Kode ini harus sesuai dengan penjelasan logika yang dijelaskan di atas untuk kasus pertama (ketika
playerAngle
<
hingeAngle
), tetapi juga menangani kasus kedua (ketika
playerAngle
>
hingeAngle
).
- Jika titik lipat saat ini yang paling dekat dengan siput memiliki nilai 1 pada titik di mana
playerAngle
< hingeAngle
, maka kami menghapus titik ini dan melakukan pengembalian sehingga sisa metode tidak dieksekusi. - Jika tidak, jika titik bengkok tidak ditandai terakhir dengan nilai 1 , tetapi
playerAngle
kurang dari hingeAngle
, maka -1 ditugaskan. - Jika titik lipat saat ini yang paling dekat dengan siput adalah -1 pada titik di mana
playerAngle
> hingeAngle
, kemudian hapus titik dan kembali. - Jika tidak, kami menetapkan entri dalam kamus titik lengkung pada posisi engsel ke 1 .
Kode ini memastikan bahwa kamus
wrapPointsLookup
selalu diperbarui, memastikan bahwa nilai titik tekuk saat ini (paling dekat dengan siput) cocok dengan sudut siput saat ini relatif terhadap titik tekuk.
Jangan lupa bahwa nilainya -1 ketika sudut slug kurang dari sudut engsel (relatif ke titik referensi), dan 1 ketika sudut slug lebih besar dari sudut engsel.
Sekarang kita akan
UnwrapRopePosition()
dalam skrip
RopeSystem dengan kode yang akan langsung terlibat dalam pelepasan, memindahkan posisi referensi dan menetapkan nilai jarak baru ke nilai jarak tali DistanceJoint2D. Tambahkan baris berikut ke disk metode yang dibuat sebelumnya:
- Indeks titik jangkar saat ini (posisi kedua tali dari siput) menjadi posisi baru dari engsel, dan posisi lama dari engsel dilepas (yang sebelumnya paling dekat dengan siput dan yang sekarang kita "lepaskan"). Variabel
newAnchorPosition
diberikan nilai anchorIndex
dalam daftar posisi tali. Kemudian akan digunakan untuk memposisikan posisi yang diperbarui dari titik jangkar. - Tali-sambungan RigidBody2D (dimana tali DistanceJoint2D terpasang) mengubah posisinya ke posisi baru dari titik jangkar. Hal ini memastikan gerakan siput terus menerus yang lancar pada tali ketika terhubung ke DistanceJoint2D, dan koneksi ini harus memungkinkannya untuk terus berayun relatif terhadap posisi baru, yang menjadi referensi - dengan kata lain, relatif ke titik berikutnya turun tali dari posisinya.
- Maka Anda perlu memperbarui nilai jarak distanceJoint2D untuk memperhitungkan perubahan tajam dalam jarak dari siput ke titik referensi baru. Jika ini belum dilakukan, pemeriksaan cepat dari flag
distanceSet
dilakukan, dan jarak diberikan nilai jarak yang dihitung antara siput dan posisi baru dari titik jangkar.
Simpan skrip dan kembali ke editor. Mulai permainan lagi dan perhatikan bagaimana tali terlepas dari tepi ketika siput melewati nilai ambang batas dari setiap titik tikungan!
Meskipun logikanya sudah siap, kami akan menambahkan beberapa kode pembantu ke
HandleRopeUnwrap()
tepat sebelum membandingkan
playerAngle
dengan
hingeAngle
(
if (playerAngle < hingeAngle)
).
if (!wrapPointsLookup.ContainsKey(hingePosition)) { Debug.LogError("We were not tracking hingePosition (" + hingePosition + ") in the look up dictionary."); return; }
Sebenarnya, ini seharusnya tidak terjadi, karena kami mendefinisikan ulang dan melepaskan kait kucing ketika membungkus sekitar satu tulang rusuk dua kali, tetapi jika ini masih terjadi, kita dapat dengan mudah keluar dari metode ini dengan
return
sederhana dan pesan kesalahan di konsol.
Selain itu, berkat ini, kami akan lebih mudah menangani kasus pembatas seperti itu; Selain itu, kami mendapatkan pesan kesalahan kami sendiri jika terjadi sesuatu yang tidak perlu.
Ke mana harus pergi selanjutnya?
Berikut ini
tautan ke proyek yang sudah selesai pada bagian kedua dan terakhir dari tutorial ini.
Selamat telah menyelesaikan seri tutorial ini! Ketika datang untuk membandingkan sudut dan posisi, semuanya menjadi sangat rumit, tetapi kami selamat dari ini dan sekarang kami memiliki sistem kait-kucing dan tali yang indah yang dapat berakhir pada objek dalam permainan.
Tahukah Anda bahwa tim pengembangan Persatuan kami telah menulis buku? Jika tidak, lihat
Unity Games By Tutorials . Game ini akan mengajarkan Anda cara membuat empat game yang sudah jadi dari awal:
- Penembak dua tongkat
- Penembak orang pertama
- Game menara pertahanan (dengan dukungan VR!)
- Platformer 2D
Setelah membaca buku ini, Anda akan belajar cara membuat game sendiri untuk Windows, macOS, iOS, dan platform lainnya!
Buku ini ditujukan untuk pemula dan mereka yang ingin meningkatkan keterampilan Persatuan mereka ke tingkat profesional. Untuk menguasai buku ini, Anda harus memiliki pengalaman pemrograman (dalam bahasa apa pun).