Saya akan berbicara dari sedikit pengalaman, beralih dari desain OO yang kaku ke desain Entity-Component-System (ECS).
Beberapa waktu yang lalu saya sama seperti Anda , saya memiliki banyak jenis benda yang memiliki sifat serupa dan saya membangun berbagai benda dan mencoba menggunakan warisan untuk menyelesaikannya. Orang yang sangat pintar bilang tidak melakukannya, dan sebagai gantinya, gunakan Entity-Component-System.
Sekarang, ECS adalah konsep besar, dan sulit untuk melakukannya dengan benar. Ada banyak pekerjaan yang dilakukan di dalamnya, membangun entitas, komponen, dan sistem dengan benar. Namun, sebelum kita dapat melakukan itu, kita perlu mendefinisikan persyaratannya.
- Entitas : inilah masalahnya , pemain, hewan, NPC, apa pun . Itu adalah hal yang membutuhkan komponen yang melekat padanya.
- Komponen : ini adalah atribut atau properti , seperti "Nama" atau "Usia", atau "Orangtua", dalam kasus Anda.
- Sistem : ini adalah logika di balik komponen, atau perilaku . Biasanya, Anda membangun satu sistem per komponen, tetapi itu tidak selalu mungkin. Selain itu, terkadang sistem perlu memengaruhi sistem lain .
Jadi, di sinilah saya akan pergi dengan ini:
Pertama dan terpenting, buat ID
untuk karakter Anda. An int
,, Guid
terserah kamu. Ini adalah "Entitas".
Kedua, mulailah berpikir tentang berbagai perilaku yang telah Anda lakukan. Hal-hal seperti "Family Tree" - itu adalah perilaku. Alih-alih memodelkan itu sebagai atribut pada entitas, membangun sistem yang menampung semua informasi itu . Sistem kemudian dapat memutuskan apa yang harus dilakukan dengannya.
Demikian juga, kami ingin membangun sistem untuk "Apakah karakternya hidup atau mati?" Ini adalah salah satu sistem terpenting dalam desain Anda, karena memengaruhi semua yang lain. Beberapa sistem dapat menghapus karakter "mati" (seperti sistem "sprite"), sistem lain secara internal dapat mengatur ulang hal-hal untuk lebih mendukung status baru.
Anda akan membangun sistem "Sprite" atau "Drawing" atau "Rendering", misalnya. Sistem ini akan memiliki tanggung jawab untuk menentukan karakter apa yang perlu ditampilkan dengan sprite, dan bagaimana cara menampilkannya. Kemudian, ketika sebuah karakter mati, hapus mereka.
Selain itu, sistem "AI" yang dapat memberi tahu karakter apa yang harus dilakukan, ke mana harus pergi, dll. Ini harus berinteraksi dengan banyak sistem lain, dan membuat keputusan berdasarkan pada mereka. Sekali lagi, karakter mati mungkin dapat dihapus dari sistem ini, karena mereka tidak benar-benar melakukan apa-apa lagi.
Sistem "Nama" dan sistem "Pohon Keluarga" Anda mungkin harus menyimpan karakter (hidup atau mati) di memori. Sistem ini perlu mengingat kembali info itu, apa pun keadaan karakternya. (Jim masih Jim, bahkan setelah kami menguburkannya.)
Ini juga memberi Anda manfaat mengubah ketika sistem bereaksi lebih efisien: sistem memiliki timer sendiri. Beberapa sistem perlu menyala dengan cepat, beberapa tidak. Di sinilah kita mulai masuk ke apa yang membuat permainan berjalan efisien. Kita tidak perlu menghitung ulang cuaca setiap milidetik, kita mungkin bisa melakukannya setiap 5 atau lebih.
Ini juga memberi Anda pengungkitan yang lebih kreatif: Anda dapat membangun sistem "Pathfinder" yang dapat menangani perhitungan lintasan dari A-ke-B, dan dapat memperbarui seperlunya, memungkinkan sistem Gerakan untuk mengatakan "di mana saya harus pergi selanjutnya? " Kami sekarang dapat sepenuhnya memisahkan masalah ini, dan alasan tentang mereka lebih efektif. Gerakan tidak perlu menemukan jalan, hanya perlu membawa Anda ke sana.
Anda akan ingin mengekspos beberapa bagian dari sistem ke luar. Di Pathfinder
sistem Anda, Anda mungkin menginginkan Vector2 NextPosition(int entity)
. Dengan cara ini, Anda dapat menyimpan elemen-elemen itu dalam array atau daftar yang dikontrol ketat. Anda dapat menggunakan struct
tipe yang lebih kecil, yang dapat membantu Anda menjaga komponen dalam blok memori yang lebih kecil dan bersebelahan, yang dapat membuat pembaruan sistem lebih cepat. (Terutama jika pengaruh eksternal ke sistem minimal, sekarang hanya perlu peduli dengan keadaan internal, seperti Name
.)
Tapi, dan saya tidak bisa cukup menekankan hal ini, sekarang Entity
ini hanyalah sebuah ID
, termasuk ubin, objek, dll. Jika suatu entitas tidak termasuk dalam suatu sistem, maka sistem tidak akan melacaknya. Ini berarti kita dapat membuat objek "Pohon", menyimpannya di dalam Sprite
dan Movement
sistem (pohon tidak akan bergerak, tetapi mereka memiliki komponen "Posisi"), dan menjauhkan mereka dari sistem lain. Kita tidak lagi memerlukan daftar khusus untuk pohon, karena memberikan pohon tidak berbeda dengan karakter, selain dari penggantungan kertas. (Yang Sprite
dapat dikontrol sistem, atau Paperdoll
sistem yang dapat dikontrol.) Sekarang kita NextPosition
dapat ditulis ulang:, Vector2? NextPosition(int entity)
dan dapat mengembalikan null
posisi untuk entitas yang tidak dipedulikannya. Kami juga menerapkan ini pada kami NameSystem.GetName(int entity)
, ia mengembalikan null
pohon dan batu.
Saya akan mengakhiri ini, tetapi idenya di sini adalah untuk memberi Anda beberapa latar belakang tentang ECS, dan bagaimana Anda benar - benar dapat memanfaatkannya untuk memberi Anda desain yang lebih baik pada gim Anda. Anda dapat meningkatkan kinerja, memisahkan elemen-elemen yang tidak terkait, dan menjaga hal-hal dalam cara yang lebih terorganisir. (Ini juga berpasangan dengan baik dengan bahasa / pengaturan fungsional, seperti F # dan LINQ, yang saya sangat merekomendasikan memeriksa F # jika Anda belum melakukannya, itu berpasangan sangat baik dengan C # ketika Anda menggunakannya bersama-sama.)