Mengapa Unity menggunakan refleksi untuk mendapatkan metode pembaruan?

12

Mengapa Unity menggunakan refleksi untuk mengakses MonoBehaviourmetode pesan seperti Awake,Update , Start, ...?

Bukankah lambat menggunakan refleksi? Mengapa tidak memanfaatkan pendekatan lain seperti Template Method? Itu hanya bisa mendefinisikan metode sebagai abstrak di MonoBehaviourkelas dasar dan memaksa subclass untuk mengimplementasikannya.

Emad
sumber

Jawaban:

20

Tidak

Bagaimana Pembaruan disebut

Tidak, Unity tidak menggunakan System.Reflection untuk menemukan metode ajaib setiap kali perlu memanggil satu.

Sebagai gantinya, pertama kali MonoBehaviour dari jenis yang diberikan diakses skrip yang mendasarinya diperiksa melalui runtime scripting (baik Mono atau IL2CPP) apakah ia memiliki metode sihir yang ditentukan dan informasi ini di-cache. Jika MonoBehaviour memiliki metode khusus, ia ditambahkan ke daftar yang tepat, misalnya jika skrip memiliki metode Pembaruan yang ditetapkan, maka ditambahkan ke daftar skrip yang perlu diperbarui setiap frame.

Selama permainan, Unity hanya mengulangi daftar-daftar ini dan menjalankan metode darinya - sesederhana itu. Juga, inilah mengapa tidak masalah jika metode Pembaruan Anda bersifat publik atau pribadi.

Adapun alasannya dilakukan dengan cara ini, saya akan merujuk Anda (pembaca) ke jawaban DMGregory , yang bermuara pada dua hal yang saling bersaing:

  1. Optimalisasi kinerja
  2. Kemudahan pemanfaatan pengembang baru

Pengembang baru hanya menginginkannya untuk Bekerja dan tidak mau harus mencari tahu "bagaimana cara menghubungkan ini ke sistem acara?" tetapi harus tetap berjalan cepat dengan overhead yang minimal.

Solusinya mungkin yang terbaik yang bisa dicapai dalam dua kendala ini. Atau setidaknya, yang terbaik yang bisa dihasilkan oleh tim Unity dev pada saat itu. Kita mungkin tidak pernah tahu.

Draco tidak lagi percaya pada SE
sumber
2
tl; dr proses yang sama, berbeda, API lebih cepat. Tetapi mengapa mereka tidak memilih metode yang berbeda seperti yang diminta oleh OP?
keajaiban
10
Kita seharusnya tidak menyangkal kemungkinan alasan "desain buruk" yang lama. Setelah rilis kode sumber c #, pengguna telah menemukan banyak kesalahan dan keputusan desain yang tidak dapat dijelaskan. Beberapa gamedev akhirnya bisa memahami perilaku tak terduga yang mereka lawan selama bertahun-tahun.
Ekserion
Selain masalah teknis, ini adalah hal pertama yang dipelajari pendatang baru, sehingga harus mudah ditambahkan atau dilewati.
Nikaas
6
Mungkin juga ada alasan historis untuk desain ini. Unity dimulai dengan bahasa scripting mereka sendiri, yang kemudian secara bertahap dihapus demi C #. Wajar jika mereka ingin tetap menggunakan pola yang sama, bahkan jika itu dimaksudkan untuk menipu sedikit.
Philipp
3
Saya pikir kita dapat dengan bermanfaat menjawab "Apa yang dicapai Unity dengan ini artinya" - mis. apa kelebihannya dari koleksi metode publik abstrak yang semuanya harus diimplementasikan. Kita tidak bisa menjawab "apa yang dipikirkan para Unity dev?" tetapi kita dapat mengatasi "mengapa pendekatan ini bermanfaat bagi pengguna mesin?"
DMGregory
10

Itu hanya bisa mendefinisikan metode sebagai abstrak di kelas dasar MonoBehaviour dan memaksa subclass untuk mengimplementasikannya.

Salah satu keunggulan sistem yang digunakan Unity adalah Anda tidak harus mengimplementasikan setiap pesan MonoBehaviour, yang jumlahnya lebih dari 60 .

Biasanya kita hanya membutuhkan satu atau beberapa metode ini. Karena beberapa khusus untuk fisika 2D / 3D, beberapa unik untuk kamera atau sistem partikel, sangat tidak mungkin ada satu skrip pun yang membutuhkan semuanya.

Dengan meninggalkan pesan yang tidak kita perlukan sebagai tidak diimplementasikan, kita dapat dengan jelas memberi sinyal ke runtime "bahkan tidak perlu repot memanggil OnCollisionStay2D pada objek ini - aku tidak membutuhkannya"

Ini bisa menjadi kemenangan efisiensi yang substansial. Sekarang mesin dapat memfilter daftar pendek untuk memanggil Pembaruan hanya pada ~ 20 objek dalam adegan saya yang membutuhkan logika pembaruan kustom setiap frame, dan tidak semua ~ 200 objek yang membentuk semua pemandangan atau hanya menanggapi peristiwa fisika.

DMGregory
sumber
Hanya pertanyaan ... sejauh yang saya tahu (tidak secara pribadi), jika Anda memiliki ribuan GameObjects, yang semuanya menggunakan skrip dengan metode Pembaruan, Anda memiliki dampak kinerja yang signifikan. Alternatifnya adalah menggunakan daftar dan beralih melalui mereka dengan hanya satu metode Pembaruan dalam skrip manajer, yang tampaknya jauh lebih berkinerja. Apakah masih demikian, atau apakah sudah berubah? - Jika tidak ada yang berubah, itu akan menyiratkan bahwa cara Unity untuk melakukannya tidak mendekati optimal mengenai kinerja.
Pertempuran
4
@Mengalahkan apa yang Anda gambarkan konsisten dengan tautan yang dikutip Draco18s dari 2015, dan saya menduga itu masih benar. Mampu membiarkan metode Pembaruan tidak terdefinisi pada ribuan objek itulah yang memungkinkan pengoptimalan ini berfungsi. Jika setiap MonoBehaviour memiliki metode Pembaruan yang didefinisikan melalui kelas dasar abstrak seperti yang dijelaskan di bagian pertanyaan yang saya kutip, maka kami tidak akan memiliki kemampuan untuk membatasi panggilan pembaruan kami hanya pada iterasi daftar manajer. Perhatikan bahwa T&J ini tidak membahas "Apakah pendekatan Unity optimal?" tetapi hanya bagaimana pendekatan saat ini dapat bermanfaat.
DMGregory
Ah saya mengerti, itu memang masuk akal. Terima kasih atas jawabannya!
Pertempuran
@Battle Ini masih benar. Sementara hal yang dilakukan Unity lebih performant daripada alternatifnya, ia masih memiliki overhead yang lebih tinggi daripada pemanggilan fungsi biasa.
Draco18s tidak lagi mempercayai SE
@ Draco18s - Ya. Saya sudah menerapkan UpdateManager untuk proyek-proyek saya yang menangani optimasi itu sejak lama. Saya hanya ingin konfirmasi bahwa masih diperlukan / berguna.
Pertempuran