Bekerja dengan status karakter. Eksperimen Persatuan

Ketika mengembangkan game di Unity, saya menemukan tugas yang menarik: bagaimana membuat waktu tindakan yang bisa diperluas dengan efek negatif atau positif pada karakter.

Singkatnya, saya memiliki karakter yang dapat diterapkan efek tertentu, seperti melemahnya, penguatan, peningkatan kecepatan, penurunan kecepatan, dan lainnya. Untuk memberi tahu pemain tentang efek efek, game menyediakan garis status.

Versi pertama dari baris ini berisi ikon-ikon gelap dari semua status dan ketika efek terjadi, cahaya yang diinginkan menyala.

gambar

Setiap status memiliki corutin, yang membatalkan efek setelah jumlah waktu tertentu.
Ada minus yang agak penting dalam keputusan ini. Jika, sebagai akibat dari peristiwa tertentu dalam permainan, efek yang sama diterapkan pada karakter setelah waktu yang lebih singkat daripada durasi efek yang sama sebelumnya, maka mungkin ada dua versi peristiwa.

  1. Cukup salah: Korutin kedua diluncurkan bersamaan dengan yang pertama. Ketika yang pertama selesai, ia kembali ke nilai aslinya, yaitu, efeknya dihapus sebelum coroutine kedua selesai bekerja.

    gambar
  2. Juga salah, tetapi dalam beberapa kasus dapat diterima: Batalkan coroutine pertama dan jalankan yang kedua. Dalam hal ini, durasi efek akan sama dengan durasi efek pertama sampai coroutine dibatalkan + durasi coroutine kedua.

    gambar

Kedua metode tidak dapat diterima untuk tugas saya, karena saya perlu memperpanjang durasi efek, sehingga saya mendapatkan jumlah durasi setiap efek, terlepas dari berapa kali efek diterapkan.

Jika karakter menginjak paku, kakinya rusak kondisional dan dia tidak bisa terus bergerak dengan kecepatan yang sama. Katakanlah kecepatan berkurang 5 detik. Jika setelah 3 detik karakter menginjak paku lain, maka kecepatan harus dikurangi dengan 5 detik lainnya. Artinya, 3 detik telah berlalu, 2 + 5 detik tersisa dari paku baru. Durasi efek harus berlangsung 7 detik dari saat serangan pada paku kedua (total 10).

Dan dengan bantuan coroutine, saya tidak menemukan solusi untuk masalah ini, karena tidak mungkin untuk mengetahui waktu yang tersisa sampai selesainya coroutine untuk menambahkannya ke coroutine baru.

Solusi yang saya temukan untuk masalah ini adalah menggunakan kamus. Keuntungannya dibandingkan Daftar adalah bahwa kamus memiliki kunci dan nilai, yang berarti saya dapat mengakses nilai apa pun dengan kunci. Plus, solusi ini memungkinkan Anda untuk menyingkirkan ikon status permanen di baris dan memasukkan yang diperlukan sesuai kebutuhan dan mengaturnya di posisi di baris sesuai urutannya.

Dictionary<string, float> statusTime = new Dictionary<string, float>(); 

Kamus dalam hal ini lebih menguntungkan daripada menggunakan antrian, karena antrian bekerja sesuai dengan prinsip-prinsip First In First Out, tetapi durasi efeknya berbeda, yang berarti bahwa status yang perlu dihapus mungkin bukan yang pertama dalam antrian.

Untuk ini, saya menambahkan tiga metode.

Addstatus

Tambahkan status yang diinginkan ke kamus, jika status tersebut sudah ada di kamus, lalu tambahkan durasinya. Jika tidak ada status, maka kami menghitung waktu akhir dan menambahkannya ke kamus.

 private void AddStatus(string status, float duration) { if (statusTime.ContainsKey(status)) { statusTime[status] += duration; } else { float endTime = Time.timeSinceLevelLoad + duration; statusTime.Add(status, endTime); } } 

RemoveStatus

Kami menghapus status dari kamus, mengembalikan nilai aslinya.

 private void RemoveStatus(string status) { statusTime.Remove(status); RestoreStats(status); } 

Status checkst

Jika ada status dalam kamus, maka kami memeriksa untuk melihat apakah waktu mereka telah kedaluwarsa.

Jika kedaluwarsa, maka hapus status dari kamus. Karena mengubah kamus di loop tidak memungkinkan untuk menyinkronkan nilai-nilai kamus, kami melempar kunci kamus di sini ke dalam Daftar reguler.

 private void CheckStatuses() { if (statusTime.Count > 0) { float currTime = Time.timeSinceLevelLoad; List<string> statuses = new List<string>(statusTime.Keys);  foreach (string stat in statuses) { if (currTime > statusTime[stat]) { RemoveStatus(stat); } } } } 

Dari plus, jelas, ini adalah durasi efek yang dapat diperpanjang. Artinya, masalah terpecahkan.
Tapi minus yang agak signifikan hadir di sini. Memeriksa status dilakukan di Perbarui setiap bingkai. Dalam permainan saya ada maksimal 4 pemain, yang berarti metode ini akan dieksekusi setiap frame 4 kali secara paralel. Dengan 4 karakter, saya pikir ini tidak kritis, tetapi saya yakin bahwa dengan lebih banyak karakter, ini dapat menyebabkan masalah kinerja. Perlu juga dicatat bahwa metode ini dilindungi dengan memeriksa keberadaan elemen dalam kamus, dan dengan kamus kosong, beban harus dikurangi.

Melihat ke depan ke masa depan (yang masih sepenuhnya berkabut untuk game ini), saya juga yakin dengan keputusan ini dalam mode online, karena cek untuk status pemain hanya akan terjadi untuk pemain lokal saat ini, dan tidak untuk semua pemain yang dipakai.

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


All Articles