Bagaimana cara menghindari "Blob-Systems" dalam sistem komponen entitas?

10

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:

  1. 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.
  2. 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?

M0rgenstern
sumber

Jawaban:

11

Ya, Anda berpikir terlalu rumit.

Kedengarannya seperti banyak masalah Anda dapat diselesaikan dengan sistem pesan dan beberapa atribut tambahan yang memungkinkan Anda untuk menentukan beberapa filter , dan akhirnya tidak khawatir menjadi begitu ketat dengan entitas / komponen.

Pesan akan membantu Anda dengan beberapa aspek seperti memicu partikel, powerups, dan sebagainya. Misalnya, Anda bisa memiliki objek dunia yang berlangganan peristiwa partikel dan membuat partikel pada posisi yang dijelaskan dalam peristiwa tersebut.

Filter akan banyak membantu Anda dalam tabrakan. Filter dapat menentukan apakah suatu objek bertabrakan dengan yang lain, dan apa responsnya. Anda menambahkan beberapa atribut ke komponen fisika Anda yang menentukan tipe tubuh fisika apa itu, tipe-tipe lain dari tubuh fisika yang bertabrakan dengannya dan seperti apa responsnya. Misalnya, objek fisika bola bertabrakan dengan objek fisika dayung dan merespons dengan pantulan dan partikel.

Akhirnya, jangan terlalu ketat tentang implementasi Anda. Jika Anda dapat menemukan cara untuk membuatnya bekerja, tetapi itu bukan sistem EC, lakukanlah. Seperti dalam contoh saya di atas, partikel tidak perlu dikelola oleh sistem atau bagian dari sistem EC sama sekali. Lebih penting untuk menyelesaikan permainan daripada mengikuti metode yang sudah didefinisikan dengan buruk.

MichaelHouse
sumber
Terima kasih banyak. Saya ingin membuat game dengan menggunakan ECS hanya untuk melihat bagaimana skala dan jika itu benar-benar baik untuk digunakan saat saya membaca di artikel dan tutorial. Masalah saya adalah saya berpikir: "Saya memiliki ECS sekarang dan semuanya harus dikelola dengan ini." Jadi saya berencana juga untuk menulis sistem partikel sehubungan dengan ECS. Juga, saya membaca di beberapa artikel bahwa setiap komponen harus benar-benar hanya memiliki beberapa data dasar dan tidak lebih. Itu sering masalah saya ... Saya pikir terlalu rumit.
M0rgenstern
Saya ingin membuat game dengan menggunakan ECS hanya untuk melihat bagaimana skala dan jika itu benar-benar baik untuk digunakan saat saya membaca di artikel dan tutorial . Jika itu adalah tujuan Anda, saya sarankan Anda melihat sistem Komponen / Entitas yang ada daripada membangun Anda sendiri. Unduh Unity3D, yang mungkin "Komponen murni yang bisa didapat" dan mainkan di sana. Wawasan yang jauh lebih cepat, IMHO.
Imi
3
@ lmi: Unity bukan Sistem Komponen Entitas meskipun berbasis komponen. ECS memiliki beberapa pedoman yang lebih ketat ( tidak pernah menganggap suatu pola sebagai aturan) daripada hanya memiliki dan menggunakan komponen objek game. Karena serangkaian artikel ECS populer dengan beberapa segmen pengembang game saat ini sehingga ada banyak pertanyaan tentang ECS ​​secara khusus daripada desain berbasis komponen secara umum.
Sean Middleditch
12

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 dan vec2(1,1)untuk bola yang menunjukkan bahwa ia dapat bergerak), sebuah bendera atau pelampung yang menunjukkan goyang ( bola biasanya akan di 1.0dan 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.

Sean Middleditch
sumber
1
Terima kasih sekali! Saya tahu, bahwa ECS tidak skala dengan sangat baik untuk permainan kecil seperti pong. Tetapi saya menggunakannya hanya untuk melihat bagaimana hal seperti itu benar-benar diterapkan dan bagaimana cara kerjanya. Saya membuat komponen sangat kecil, karena itulah yang saya baca sebagian besar di beberapa artikel. Untuk memiliki banyak komponen dan setiap komponen hanya menyimpan data dasar. Jadi, apakah saya mengerti Anda benar, bahwa Anda menyarankan untuk menggunakan campuran antara warisan dan ECS? Seperti yang Anda katakan "bola dan dayung cukup berbeda untuk menjadi komponen yang terpisah". Jadi misalnya saya memberi mereka keduanya komponen Gerakan / Posisi (mungkin sebagai satu komponen) dan
M0rgenstern
1
Apapun yang berhasil. Fokus membuat game. Saya benar-benar hanya akan memiliki komponen yang disebut Ballyang berisi semua logika untuk bola seperti gerakan, memantul, dll. Dan Paddlekomponen 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.
Sean Middleditch
3
Saya benar-benar hanya akan memiliki komponen yang disebut Bola yang berisi semua logika untuk bola seperti gerakan, memantul, dll. Dan komponen Paddle yang mengambil input, tapi itu saya. Dan itu sebabnya ada satu pendapat untuk setiap programmer tentang "apa itu sistem komponen tentang". Saya sarankan TIDAK untuk melakukannya seperti saran ini, kecuali Anda benar-benar berpikir dalam sistem Entity klasik dan dipaksa untuk menggunakan sistem Komponen tetapi tidak ingin melihat apa perbedaan sebenarnya.
Imi
2
@ lmi: pernah mengerjakan beberapa game / mesin besar dengan komponen dan melihat langsung mengapa kami menggunakan komponen, tidak, komponen yang terlalu granular hanya lebih merepotkan daripada nilainya. Komponen bukanlah peluru ajaib; mereka adalah salah satu dari banyak alat di kotak peralatan pengembang game. Gunakan mereka dengan cara dan tempat yang mereka bantu dan bukan dengan cara yang mereka tambahkan lebih banyak overhead mental dan runtime ke sistem. Jika satu-satunya hal yang memiliki bola-fisika adalah bola, ada nol keuntungan untuk memisahkannya dari sifat bola lainnya. Jika dan ketika itu berubah, bagilah hanya itu.
Sean Middleditch
1
Saya setuju prinsip menjadi pragmatis dan tidak membiarkan derai tertentu menghalangi mereka. TETAPI jika ECS tidak dapat menangani game sepele ini tanpa penyimpangan, harapan apa yang ada untuk sebuah game besar. Saya juga mencoba belajar bagaimana menggunakan ECS secara efektif, tetapi saya mencoba untuk tetap sedekat mungkin dengan filosofi ECS, jika tidak, setelah saya mulai membuat pengecualian dan kasus khusus, saya tahu saya akan berakhir dengan kekacauan yang tidak dapat dipelihara.
Ken
-2

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:

  • Anda benar-benar ingin membalikkan ketergantungan: Komponen lain harus mendengarkan acara / pesan / siaran / kait / bagaimana setiap orang melakukan kesalahan untuk mengeksekusi logika mereka dalam menanggapi komponen Anda saat ini. Komponen saat ini bahkan tidak perlu tahu bahwa ada komponen "lain". Ini yang paling sering terjadi, jika Anda menemukan diri Anda memanggil komponen yang berbeda (bahkan di blok lain / case berbeda) dengan fungsi yang tidak benar-benar terhubung ke metode Anda saat ini. Pikirkan semua ini Invalidate()atau SetDirty()panggilan ke komponen lain.
  • Anda mungkin memiliki terlalu banyak komponen. Jika dua komponen tidak bisa hidup tanpa satu sama lain dan terus-menerus perlu mengambil data dan memanggil metode satu sama lain, maka gabungkan saja. Jelas, fungsi yang mereka berikan sangat terjerat, yang sebenarnya hanya satu hal.

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)

I MI
sumber