Saat ini saya menghadapi masalah berikut:
Saya mencoba untuk menulis klon pong dengan menggunakan sistem komponen entitas (ECS). Saya menulis "kerangka" sendiri. Jadi ada kelas yang mengelola entitas dengan semua komponen. Lalu ada kelas komponen itu sendiri. Dan terakhir ada sistem saya yang hanya mendapatkan semua entitas yang memiliki komponen yang dibutuhkan sistem.
Jadi misalnya sistem pergerakan saya mencari semua entitas yang memiliki komponen posisi dan komponen gerakan. Komponen posisi hanya menahan posisi dan komponen gerakan menahan kecepatan.
Tetapi masalah sebenarnya adalah sistem tabrakan saya. Kelas ini seperti gumpalan logis. Saya punya begitu banyak kasus khusus di kelas ini.
Sebagai contoh: Dayung saya dapat bertabrakan dengan perbatasan. Jika ini terjadi, kecepatannya disetel ke nol. Bola saya juga bisa bertabrakan dengan perbatasan. Tetapi dalam hal ini kecepatannya hanya dicerminkan pada batas normal sehingga tercermin. Untuk melakukan ini saya memberi bola komponen fisika tambahan yang hanya mengatakan: "Hei, benda ini tidak berhenti, itu mencerminkan." Jadi sebenarnya, komponen fisika tidak memiliki data nyata. Ini adalah kelas kosong yang hanya ada di sana untuk memberi tahu sistem jika suatu objek mencerminkan atau berhenti.
Lalu datang ini: Saya ingin memberikan beberapa partikel ketika bola bertabrakan dengan dayung atau perbatasan. Jadi saya pikir bola harus mendapatkan komponen lain yang memberitahu sistem tumbukan untuk membuat partikel pada tumbukan.
Kemudian saya ingin memiliki power up yang dapat bertabrakan dengan dayung tetapi tidak dengan perbatasan. Jika itu terjadi, power-up harus menghilang. Jadi saya akan membutuhkan lebih banyak case dan komponen (untuk memberi tahu sistem bahwa beberapa entitas hanya dapat bertabrakan dengan yang lain, bot tidak dengan semua bahkan jika beberapa yang lain benar-benar dapat bertabrakan, lebih jauh sistem tabrakan harus menerapkan power-up ke dayung, dll, dll, dll.).
Saya melihat bahwa sistem komponen entitas adalah hal yang baik karena fleksibel dan Anda tidak memiliki masalah dengan warisan. Tapi saya benar-benar terjebak saat ini.
Apakah saya berpikir terlalu rumit? Bagaimana saya harus mengatasi masalah ini?
Tentu, saya harus membuat sistem yang sebenarnya bertanggung jawab untuk "pasca-tabrakan", sehingga sistem tabrakan hanya mengatakan "Ya, kami memiliki tabrakan di frame terakhir" dan kemudian ada banyak sistem "pasca-tabrakan" yang semua membutuhkan komponen (kombinasi) yang berbeda dan kemudian mengubah komponen. Misalnya akan ada sistem pergerakan pasca-tabrakan yang menghentikan hal-hal yang harus berhenti ketika tabrakan terjadi. Kemudian sistem pasca-tabrakan fisika yang mencerminkan hal-hal, dll.
Tetapi ini sepertinya juga bukan solusi yang tepat bagi saya, karena misalnya:
- Sistem pasca-tabrakan gerakan saya akan membutuhkan entitas yang memiliki komponen posisi, komponen gerakan dan komponen tabrakan. Maka itu akan mengatur kecepatan entitas menjadi nol.
- Sistem fisika pasca-tabrakan akan membutuhkan entitas yang memiliki komponen posisi, komponen gerakan, komponen tabrakan, dan komponen fisika. Maka itu akan mencerminkan vektor kecepatan.
Masalahnya jelas: Gerakan pasca-tabrakan membutuhkan entitas yang merupakan subset dari entitas dalam fisika pasca-tabrakan. Jadi dua sistem pasca-tabrakan akan beroperasi pada data yang sama, efeknya adalah: Meskipun suatu entitas memiliki komponen fisika, kecepatannya akan menjadi nol setelah tabrakan.
Bagaimana masalah ini diselesaikan secara umum dalam sistem komponen entitas? Apakah masalah itu biasa atau apakah saya melakukan sesuatu yang salah? Jika ya, apa dan bagaimana seharusnya itu dilakukan?
sumber
Anda terlalu rumit. Saya akan melangkah lebih jauh dengan mengatakan bahwa bahkan menggunakan desain berbasis komponen hanya membutuhkan sedikit tenaga untuk permainan yang begitu sederhana. Lakukan berbagai hal dengan cara yang membuat gim Anda cepat dan mudah dikembangkan. Komponen membantu dengan iterasi dalam proyek yang lebih besar dengan beragam perilaku dan konfigurasi objek game, tetapi manfaatnya untuk game sederhana yang terdefinisi lebih dipertanyakan. Saya melakukan pembicaraan tahun lalu tentang ini: Anda dapat membangun game kecil yang menyenangkan dalam beberapa jam jika Anda fokus membuat game alih-alih mengikuti arsitektur . Warisan rusak ketika Anda memiliki 100 atau bahkan 20 jenis objek yang berbeda tetapi berfungsi dengan baik jika Anda hanya memiliki sedikit.
Dengan asumsi Anda ingin terus menggunakan komponen untuk tujuan pembelajaran, ada beberapa masalah yang jelas dengan pendekatan Anda yang menonjol.
Pertama, jangan membuat komponen Anda begitu kecil. Tidak ada alasan untuk memiliki komponen berbutir halus seperti 'gerakan'. Tidak ada gerakan generik dalam gim Anda. Anda memiliki dayung, yang gerakannya terkait erat dengan input atau AI (dan tidak benar-benar menggunakan kecepatan, akselerasi, restitusi, dll.), Dan Anda memiliki bola, yang memiliki algoritma pergerakan yang terdefinisi dengan baik. Hanya memiliki komponen PaddleController dan komponen BouncingBall atau sesuatu di sepanjang baris tersebut. Jika / ketika Anda mendapatkan gim yang lebih rumit, maka Anda bisa khawatir memiliki komponen PhysicsBody yang lebih umum (yang pada mesin 'nyata' pada dasarnya hanyalah tautan antara objek gim dan objek API internal apa pun yang digunakan oleh Havok / PhysX / Bullet / Box2D / etc.) Yang menangani berbagai situasi yang lebih luas.
Bahkan komponen 'posisi' dipertanyakan meskipun tentu tidak jarang. Mesin fisika biasanya memiliki gagasan internal mereka sendiri tentang di mana objek berada, grafik mungkin memiliki representasi yang diinterpolasi, dan AI mungkin memiliki representasi lain dari data yang sama dalam keadaan yang berbeda. Mungkin menguntungkan untuk membiarkan setiap sistem mengelola idenya sendiri tentang transformasi dalam komponen sistem itu sendiri dan kemudian memastikan ada komunikasi yang lancar antar sistem. Lihat posting blog BitSquid di aliran acara .
Untuk mesin fisika khusus, ingat bahwa Anda diizinkan memiliki data pada komponen Anda. Mungkin komponen fisika Pong generik memiliki data yang menunjukkan kapak mana yang dapat bergerak (katakanlah,
vec2(0,1)
sebagai pengganda untuk dayung yang hanya bisa bergerak pada sumbu Y danvec2(1,1)
untuk bola yang menunjukkan bahwa ia dapat bergerak), sebuah bendera atau pelampung yang menunjukkan goyang ( bola biasanya akan di1.0
dan dayung di0.0
), karakteristik akselerasi, kecepatan, dan sebagainya. Mencoba untuk membagi ini menjadi bazillion komponen mikro yang berbeda untuk setiap bagian dari data yang sangat terkait bertentangan dengan apa yang seharusnya dilakukan ECS. Menyimpan hal-hal yang digunakan bersama dalam komponen yang sama di mana mungkin dan hanya membaginya ketika ada perbedaan besar dalam bagaimana setiap objek game menggunakan data itu. Ada argumen yang menyatakan bahwa untuk Pong fisika antara bola dan dayung cukup berbeda untuk menjadi komponen yang terpisah, tetapi untuk permainan yang lebih besar, ada sedikit alasan untuk mencoba membuat 20 komponen untuk melakukan apa yang bekerja dengan baik dalam 1-3.Ingat, jika / ketika versi ECS Anda menghalanginya, lakukan apa yang Anda perlukan untuk benar-benar membuat game Anda dan melupakan kepatuhan terhadap pola desain / arsitektur.
sumber
Ball
yang berisi semua logika untuk bola seperti gerakan, memantul, dll. DanPaddle
komponen yang mengambil input, tapi itu saya. Apa pun yang paling masuk akal bagi Anda dan keluar dari jalan Anda dan membuat Anda membuat permainan adalah "cara yang benar" untuk melakukan sesuatu.Menurut pendapat saya *), masalah terbesar Anda dengan Komponen adalah ini: Komponen TIDAK di sini untuk memberi tahu orang lain apa yang harus dilakukan. Komponen di sini untuk melakukan hal-hal. Anda tidak memiliki komponen hanya untuk menyimpan memori dari beberapa hal dan kemudian memiliki komponen lain beroperasi pada ini. Anda ingin komponen yang melakukan hal-hal dengan data yang mereka dapatkan.
Jika Anda melihat diri Anda menguji keberadaan komponen lain (dan kemudian memanggil fungsi di sana), maka ini adalah tanda yang jelas, bahwa salah satu dari dua hal itu benar:
Invalidate()
atauSetDirty()
panggilan ke komponen lain.Omong-omong, ini berlaku untuk semua jenis sistem, tidak hanya sistem Entity / Component, tetapi juga untuk warisan klasik dengan fungsi "GameObject" sederhana atau bahkan pustaka.
*) Benar-benar hanya milikku . Pendapat sangat beragam tentang Whats Da Real Component Systemz (TM)
sumber