Saya telah tertarik pada sistem entitas berbasis komponen untuk sementara waktu, dan membaca artikel yang tak terhitung jumlahnya di dalamnya (The Insomiac , standar cantik Evolve Your Hierarchy , T-Machine , Chronoclast ... hanya untuk beberapa nama).
Mereka semua tampaknya memiliki struktur di luar sesuatu seperti:
Entity e = Entity.Create();
e.AddComponent(RenderComponent, ...);
//do lots of stuff
e.GetComponent<PositionComponent>(...).SetPos(4, 5, 6);
Dan jika Anda membawa ide data bersama (ini adalah desain terbaik yang saya lihat sejauh ini, dalam hal tidak menggandakan data di mana-mana)
e.GetProperty<string>("Name").Value = "blah";
Ya, ini sangat efisien. Namun, itu bukan cara termudah untuk membaca atau menulis; rasanya sangat kikuk dan bekerja melawan Anda.
Saya pribadi ingin melakukan sesuatu seperti:
e.SetPosition(4, 5, 6);
e.Name = "Blah";
Meskipun tentu saja satu-satunya cara untuk mendapatkan desain semacam itu adalah kembali ke Entity-> NPC-> Enemy-> FlyingEnemy-> FlyingEnemyWithAHat Pada jenis hierarki desain ini mencoba untuk menghindari.
Adakah yang melihat desain untuk sistem komponen semacam ini yang masih fleksibel, namun tetap mempertahankan tingkat keramahan pengguna? Dan dalam hal ini, mengelola penyimpanan data (mungkin masalah tersulit) dengan cara yang baik?
Desain apa yang ada untuk sistem entitas berbasis komponen yang ramah pengguna tetapi masih fleksibel?
sumber
Saya akan menyarankan beberapa jenis kelas Interface untuk objek Entity Anda akan lebih baik. Itu bisa melakukan penanganan kesalahan dengan memeriksa untuk memastikan suatu entitas mengandung komponen dari nilai yang sesuai juga di satu lokasi sehingga Anda tidak perlu melakukannya di mana pun Anda mengakses nilai. Bergantian, sebagian besar desain yang pernah saya lakukan dengan sistem berbasis komponen, saya berurusan dengan komponen secara langsung, meminta, misalnya, komponen posisi mereka dan kemudian mengakses / memperbarui properti komponen itu secara langsung.
Sangat mendasar pada level tinggi, kelas menerima entitas yang dimaksud dan menyediakan antarmuka yang mudah digunakan ke bagian komponen yang mendasarinya sebagai berikut:
sumber
Dengan Python, Anda dapat mencegat bagian 'setPosition'
e.SetPosition(4,5,6)
dengan mendeklarasikan__getattr__
fungsi pada Entity. Fungsi ini dapat beralih melalui komponen dan menemukan metode atau properti yang sesuai dan mengembalikannya, sehingga panggilan fungsi atau penugasan pergi ke tempat yang tepat. Mungkin C # memiliki sistem yang serupa, tetapi mungkin tidak dapat dilakukan karena diketik secara statis - mungkin tidak dapat dikompilasie.setPosition
kecuali e memiliki setPosition di antarmuka di suatu tempat.Anda mungkin juga dapat membuat semua entitas Anda mengimplementasikan antarmuka yang relevan untuk semua komponen yang mungkin Anda tambahkan ke mereka, dengan metode rintisan yang menimbulkan pengecualian. Kemudian ketika Anda memanggil addComponent, Anda hanya mengarahkan ulang fungsi entitas untuk antarmuka komponen itu ke komponen. Agak fiddly.
Tapi mungkin termudah adalah dengan membebani [] operator pada kelas Entity Anda untuk mencari komponen yang terpasang untuk keberadaan properti valid dan kembali itu, sehingga dapat ditugaskan untuk suka begitu:
e["Name"] = "blah"
. Setiap komponen perlu mengimplementasikan GetPropertyByName sendiri dan Entitas memanggil masing-masing satu per satu sampai menemukan komponen yang bertanggung jawab atas properti yang dimaksud.sumber
GetProperty
.. Satu - satunya downside adalah manipulasi string dan perbandingan. Tapi itu poin yang bisa diperdebatkan.Untuk memperluas jawaban Kylotan, jika Anda menggunakan C # 4.0, Anda bisa mengetik variabel secara dinamis menjadi dinamis .
Jika Anda mewarisi dari System.Dynamic.DynamicObject, Anda dapat mengganti TryGetMember dan TrySetMember (di antara banyak metode virtual) untuk mencegat nama-nama komponen dan mengembalikan komponen yang diminta.
Saya menulis sedikit tentang sistem entitas selama bertahun-tahun, tetapi saya menganggap saya tidak dapat bersaing dengan para raksasa. Beberapa catatan ES (agak ketinggalan jaman dan tidak mencerminkan pemahaman saya saat ini tentang sistem entitas, tetapi layak dibaca, imho).
sumber
object
parameter keluar - tetapi semua ini akan diselesaikan pada saat runtime. Saya pikir ini adalah cara yang dimuliakan untuk menjaga antarmuka yang lancar di atas entitas yaitu.TryGetComponent (compName, komponen keluar). Namun saya tidak yakin saya mengerti pertanyaannya :)Saya melihat banyak ketertarikan di sini di ES pada C #. Lihatlah port saya dari implementasi ES yang sangat baik Artemis:
https://github.com/thelinuxlich/artemis_CSharp
Juga, contoh gim untuk memulai cara kerjanya (menggunakan XNA 4): https://github.com/thelinuxlich/starwarrior_CSharp
Saran dipersilahkan!
sumber
Saya memutuskan untuk menggunakan sistem refleksi C # yang sangat baik. Saya mendasarkannya pada sistem komponen umum, ditambah campuran jawaban di sini.
Komponen ditambahkan dengan sangat mudah:
Dan dapat ditanyakan dengan nama, tipe, atau (jika yang umum seperti Kesehatan dan Posisi) berdasarkan properti:
Dan dihapus:
Data, sekali lagi, diakses secara umum oleh properti:
Yang disimpan di sisi komponen; lebih sedikit overhead jika tidak memiliki HP:
Banyaknya pengetikan dibantu oleh Intellisense dalam VS, tetapi sebagian besar ada sedikit pengetikan - hal yang saya cari.
Di belakang layar, saya menyimpan
Dictionary<Type, Component>
danComponents
menimpaToString
metode untuk memeriksa nama. Desain asli saya digunakan terutama string untuk nama dan hal-hal, tetapi menjadi babi untuk bekerja dengan (oh lihat, saya harus melempar ke mana-mana dan juga kurangnya akses mudah ke properti).sumber