Ini yang sulit. Saya hanya akan mencoba menangani beberapa pertanyaan berdasarkan pengalaman khusus saya (YMMV):
Komponen harus mengakses data komponen lainnya. Misalnya metode draw komponen render harus mengakses posisi komponen transform. Ini menciptakan dependensi dalam kode.
Jangan meremehkan jumlah dan kompleksitas (bukan derajat) dari kopling / dependensi di sini. Anda bisa melihat perbedaan antara ini (dan diagram ini sudah sangat disederhanakan menjadi level seperti mainan, dan contoh dunia nyata akan memiliki antarmuka di antara untuk melonggarkan kopling):
... dan ini:
... atau ini:
Komponen dapat berupa polimorfik yang lebih jauh memperkenalkan kompleksitas. Misalnya Mungkin ada komponen render sprite yang menimpa metode menggambar virtual komponen render.
Begitu? Setara analog (atau literal) dari pengiriman vtable dan virtual dapat dipanggil melalui sistem daripada objek yang menyembunyikan keadaan / data yang mendasarinya. Polimorfisme masih sangat praktis dan layak dengan implementasi ECS "murni" ketika vtable analog atau penunjuk fungsi berubah menjadi semacam "data" untuk dipanggil oleh sistem.
Karena behaivour polimorfik (misalnya untuk rendering) harus diimplementasikan di suatu tempat, ia hanya di-outsource ke dalam sistem. (misalnya sistem render sprite membuat simpul render sprite yang mewarisi simpul render dan menambahkannya ke mesin render)
Begitu? Saya harap ini tidak muncul sebagai sarkasme (bukan maksud saya meskipun saya sering dituduh melakukannya tetapi saya berharap saya dapat berkomunikasi emosi lebih baik melalui teks), tetapi "outsourcing" perilaku polimorfik dalam kasus ini tidak selalu menimbulkan tambahan biaya untuk produktivitas.
Komunikasi antar sistem bisa sulit dihindari. Misalnya sistem tumbukan mungkin memerlukan kotak pembatas yang dihitung dari komponen render beton apa pun yang ada.
Contoh ini tampaknya sangat aneh bagi saya. Saya tidak tahu mengapa penyaji akan mengeluarkan data kembali ke tempat kejadian (saya biasanya menganggap penyaji hanya baca dalam konteks ini), atau agar penyaji mencari tahu AABB alih-alih sistem lain untuk melakukan ini untuk penyaji dan tabrakan / fisika (saya mungkin akan terpaku pada nama "komponen render" di sini). Namun saya tidak ingin terlalu terpaku pada contoh ini karena saya sadar bukan itu yang ingin Anda sampaikan. Tetap saja komunikasi antar sistem (bahkan dalam bentuk tidak langsung membaca / menulis ke basis data ECS pusat dengan sistem yang tergantung langsung pada transformasi yang dibuat oleh orang lain) tidak perlu sering, jika perlu. Bahwa'
Ini dapat menyebabkan masalah jika urutan fungsi fungsi pembaruan sistem tidak ditentukan.
Ini mutlak harus didefinisikan. ECS bukan solusi akhir semua untuk mengatur ulang urutan evaluasi pemrosesan sistem dari setiap sistem yang mungkin dalam basis kode dan mendapatkan kembali hasil yang persis sama dengan pengguna akhir yang berurusan dengan frame dan FPS. Ini adalah salah satu hal, ketika merancang ECS, yang setidaknya saya sarankan sangat harus diantisipasi agak awal (meskipun dengan banyak ruang pernapasan memaafkan untuk mengubah pikiran kemudian asalkan tidak mengubah aspek paling kritis dari pemesanan doa / evaluasi sistem).
Namun, menghitung ulang seluruh tilemap setiap frame mahal. Oleh karena itu, daftar akan diperlukan untuk melacak semua perubahan yang dilakukan untuk kemudian memperbaruinya di sistem. Dengan cara OOP ini bisa dienkapsulasi oleh komponen peta ubin. Misalnya metode SetTile () akan memperbarui array vertex setiap kali dipanggil.
Saya tidak begitu mengerti hal ini kecuali bahwa ini adalah masalah yang berorientasi pada data. Dan tidak ada jebakan untuk merepresentasikan dan menyimpan data dalam ECS, termasuk memoisasi, untuk menghindari jebakan kinerja seperti itu (yang terbesar dengan ECS cenderung berhubungan dengan hal-hal seperti permintaan sistem untuk contoh yang tersedia dari jenis komponen tertentu yang merupakan salah satu aspek yang paling menantang dalam mengoptimalkan ECS umum). Fakta bahwa logika dan data dipisahkan dalam ECS "murni" tidak berarti Anda tiba-tiba harus menghitung ulang hal-hal yang seharusnya bisa di-cache / memo dalam representasi OOP. Itu poin yang bisa diperdebatkan / tidak relevan kecuali saya membahas sesuatu yang sangat penting.
Dengan ECS "murni" Anda masih dapat menyimpan data ini di komponen peta ubin. Satu-satunya perbedaan utama adalah bahwa logika untuk memperbarui array vertex ini akan pindah ke sistem di suatu tempat.
Anda bahkan dapat bersandar pada ECS untuk menyederhanakan pembatalan dan penghapusan cache ini dari entitas jika Anda membuat komponen terpisah seperti TileMapCache
. Pada titik itu ketika cache diinginkan tetapi tidak tersedia dalam suatu entitas dengan TileMap
komponen, Anda dapat menghitung dan menambahkannya. Ketika tidak valid atau tidak lagi diperlukan, Anda dapat menghapusnya melalui ECS tanpa harus menulis kode lebih khusus untuk pembatalan dan penghapusan tersebut.
Ketergantungan antara komponen masih ada meskipun disembunyikan dalam sistem
Tidak ada ketergantungan antara komponen dalam rep "murni" (saya tidak berpikir itu benar untuk mengatakan bahwa dependensi disembunyikan di sini oleh sistem). Data tidak tergantung pada data, jadi untuk berbicara. Logika tergantung pada logika. Dan ECS "murni" cenderung mempromosikan logika yang akan ditulis sedemikian rupa sehingga bergantung pada subset minimal absolut dari data dan logika (seringkali tidak ada) yang dibutuhkan sistem untuk bekerja, yang tidak seperti banyak alternatif yang sering mendorong bergantung pada jauh lebih banyak fungsi daripada yang dibutuhkan untuk tugas yang sebenarnya. Jika Anda menggunakan ECS benar murni, salah satu hal pertama yang harus Anda hargai adalah manfaat decoupling sambil secara bersamaan mempertanyakan semua yang pernah Anda pelajari untuk menghargai dalam OOP tentang enkapsulasi dan secara khusus menyembunyikan informasi.
Dengan decoupling secara khusus saya maksudkan betapa sedikitnya informasi yang dibutuhkan sistem Anda untuk bekerja. Sistem gerak Anda bahkan tidak perlu tahu tentang sesuatu yang jauh lebih kompleks seperti Particle
atau Character
(pengembang sistem bahkan tidak perlu tahu ide entitas seperti itu bahkan ada di sistem). Itu hanya perlu tahu tentang data minimum telanjang seperti komponen posisi yang bisa sesederhana beberapa mengapung dalam sebuah struct. Ini lebih sedikit informasi dan lebih sedikit ketergantungan eksternal daripada apa yang IMotion
cenderung dibawa oleh antarmuka murni . Ini terutama karena pengetahuan minimal ini bahwa setiap sistem mengharuskan untuk bekerja yang membuat ECS sering jadi pemaaf untuk menangani perubahan desain yang sangat tak terduga dalam belakang tanpa menghadapi kerusakan antarmuka cascading di semua tempat.
Pendekatan "tidak murni" yang Anda sarankan agak mengurangi manfaat itu karena sekarang logika Anda tidak dilokalisasi secara ketat ke sistem di mana perubahan tidak menyebabkan kerusakan berjenjang. Logikanya sekarang akan terpusat pada tingkat tertentu dalam komponen yang diakses oleh beberapa sistem yang sekarang harus memenuhi persyaratan antarmuka dari semua berbagai sistem yang dapat menggunakannya, dan sekarang itu seperti setiap sistem kemudian perlu memiliki pengetahuan tentang (tergantung pada) lebih informasi yang dibutuhkan untuk bekerja dengan komponen itu.
Ketergantungan pada Data
Salah satu hal yang kontroversial tentang ECS adalah bahwa ia cenderung untuk menggantikan apa yang seharusnya menjadi dependensi untuk antarmuka abstrak hanya dengan data mentah, dan itu umumnya dianggap sebagai bentuk kopling yang kurang diinginkan dan lebih ketat. Tetapi dalam jenis domain seperti game di mana ECS bisa sangat bermanfaat, seringkali lebih mudah untuk merancang representasi data di muka dan menjaganya tetap stabil daripada mendesain apa yang dapat Anda lakukan dengan data itu di beberapa tingkat pusat sistem. Itu sesuatu yang saya amati dengan menyakitkan bahkan di antara para veteran berpengalaman dalam basis kode yang menggunakan lebih dari pendekatan antarmuka murni gaya COM dengan hal-hal seperti IMotion
.
Para pengembang terus menemukan alasan untuk menambah, menghapus, atau mengubah fungsi ke antarmuka pusat ini, dan setiap perubahan itu mengerikan dan mahal karena akan cenderung memecah setiap kelas yang diimplementasikan IMotion
bersama dengan setiap tempat sejak dalam sistem yang digunakan IMotion
. Sementara itu sepanjang waktu dengan begitu banyak perubahan yang menyakitkan dan mengalir, objek yang diimplementasikan IMotion
semuanya hanya menyimpan matriks 4x4 float dan seluruh antarmuka hanya peduli dengan bagaimana mengubah dan mengakses float tersebut; representasi data stabil sepanjang jalan dari awal, dan banyak rasa sakit bisa dihindari jika antarmuka terpusat ini, sehingga cenderung berubah dengan kebutuhan desain yang tidak terduga, bahkan tidak ada di tempat pertama.
Ini semua bisa terdengar hampir sama menjijikkannya seperti variabel global tetapi sifat bagaimana ECS mengatur data ini menjadi komponen yang diambil secara eksplisit berdasarkan jenis melalui sistem membuatnya begitu, sementara kompiler tidak dapat menegakkan apa pun seperti menyembunyikan informasi, tempat-tempat yang mengakses dan bermutasi data umumnya sangat eksplisit dan cukup jelas untuk tetap mempertahankan invarian secara efektif dan memprediksi jenis transformasi dan efek samping apa yang terjadi dari satu sistem ke sistem berikutnya (sebenarnya dengan cara yang bisa dibilang lebih sederhana dan lebih dapat diprediksi daripada OOP dalam domain tertentu mengingat bagaimana sistem berubah menjadi semacam pipeline datar).
Terakhir, saya ingin mengajukan pertanyaan tentang bagaimana saya akan menangani animasi dalam ECS murni. Saat ini saya telah mendefinisikan animasi sebagai functor yang memanipulasi entitas berdasarkan beberapa kemajuan antara 0 dan 1. Komponen animasi memiliki daftar animator yang memiliki daftar animasi. Dalam fungsi pembaruannya itu berlaku animasi apa pun yang sedang aktif ke entitas.
Kita semua pragmatis di sini. Bahkan di gamedev Anda mungkin akan mendapatkan ide / jawaban yang bertentangan. Bahkan ECS murni adalah fenomena yang relatif baru, wilayah perintis, di mana orang belum tentu merumuskan pendapat terkuat tentang cara merawat kulit kucing. Reaksi usus saya adalah sistem animasi yang meningkatkan kemajuan animasi semacam ini dalam komponen animasi untuk ditampilkan oleh sistem rendering, tetapi itu mengabaikan begitu banyak nuansa untuk aplikasi dan konteks tertentu.
Dengan ECS itu bukan peluru perak dan saya masih menemukan kecenderungan untuk masuk dan menambahkan sistem baru, menghapus beberapa, menambahkan komponen baru, mengubah sistem yang ada untuk mengambil jenis komponen baru, dll. Saya tidak mendapatkan hal yang benar sama sekali pertama kali masih ada. Tetapi perbedaan dalam kasus saya adalah bahwa saya tidak mengubah apa pun yang penting ketika saya gagal mengantisipasi kebutuhan desain tertentu di muka. Saya tidak mendapatkan efek riak dari kerusakan berjenjang yang mengharuskan saya untuk pergi ke mana-mana dan mengubah begitu banyak kode untuk menangani beberapa kebutuhan baru yang muncul, dan itu cukup menghemat waktu. Saya juga merasa lebih mudah di otak saya karena ketika saya duduk dengan sistem tertentu, saya tidak perlu tahu / ingat banyak tentang hal lain selain komponen yang relevan (yang hanya data) untuk mengerjakannya.