Judulnya sengaja hiperbolik dan mungkin hanya pengalaman saya dengan polanya tapi inilah alasan saya:
Cara "biasa" atau bisa langsung dari entitas pelaksana adalah dengan mengimplementasikannya sebagai objek dan mensubklasifikasikan perilaku umum. Ini mengarah ke masalah klasik "adalah EvilTree
subclass dari Tree
atau Enemy
?". Jika kita mengizinkan beberapa warisan, masalah intan muncul. Sebagai gantinya, kita dapat menarik fungsionalitas gabungan Tree
dan Enemy
lebih jauh ke atas hierarki yang mengarah ke kelas-kelas Tuhan, atau kita dapat dengan sengaja meninggalkan perilaku di kelas kita Tree
dan Entity
(membuat mereka menjadi penghubung dalam kasus ekstrem) sehingga EvilTree
dapat mengimplementasikannya sendiri - yang mengarah ke duplikasi kode jika kita pernah punya SomewhatEvilTree
.
Sistem Entitas-Komponen mencoba untuk memecahkan masalah ini dengan membagi Tree
dan Enemy
objek menjadi komponen yang berbeda - katakanlah Position
, Health
dan AI
- dan menerapkan sistem, seperti AISystem
yang mengubah posisi Entitiy sesuai dengan keputusan AI. Sejauh ini bagus tapi bagaimana jika EvilTree
bisa mengambil powerup dan menangani kerusakan? Pertama kita perlu a CollisionSystem
dan DamageSystem
(kita mungkin sudah memiliki ini). The CollisionSystem
kebutuhan untuk berkomunikasi dengan DamageSystem
: Setiap kali dua hal bertabrakan dengan CollisionSystem
mengirimkan pesan ke DamageSystem
kesehatan sehingga dapat mengurangi. Kerusakan juga dipengaruhi oleh powerups sehingga kita perlu menyimpannya di suatu tempat. Apakah kita membuat yang baru PowerupComponent
yang kita lampirkan ke entitas? Tapi kemudianDamageSystem
perlu tahu tentang sesuatu yang lebih baik tidak tahu tentang - setelah semua, ada juga hal-hal yang menangani kerusakan yang tidak dapat mengambil powerups (misalnya a Spike
). Apakah kami mengizinkan PowerupSystem
untuk memodifikasi StatComponent
yang juga digunakan untuk perhitungan kerusakan yang mirip dengan jawaban ini ? Tetapi sekarang dua sistem mengakses data yang sama. Ketika permainan kami menjadi lebih kompleks, itu akan menjadi grafik ketergantungan yang tidak berwujud di mana komponen dibagi di antara banyak sistem. Pada titik itu kita bisa menggunakan variabel statis global dan menyingkirkan semua boilerplate.
Apakah ada cara yang efektif untuk menyelesaikan ini? Satu ide yang saya miliki adalah membiarkan komponen memiliki fungsi tertentu, misalnya memberikan StatComponent
attack()
yang baru saja mengembalikan integer secara default tetapi dapat dikomposisi ketika powerup terjadi:
attack = getAttack compose powerupBy(20) compose powerdownBy(40)
Ini tidak menyelesaikan masalah yang attack
harus disimpan dalam komponen yang diakses oleh banyak sistem, tetapi setidaknya saya bisa mengetik fungsi dengan benar jika saya memiliki bahasa yang mendukungnya secara memadai:
// In StatComponent
type Strength = PrePowerup | PostPowerup
type Damage = Int
type PrePowerup = Int
type PostPowerup = Int
attack: Strength = getAttack //default value, can be changed by systems
getAttack: PrePowerup
// these functions can be defined in other components or in PowerupSystems
powerupBy: Strength -> PostPowerup
powerdownBy: Strength -> PostPowerup
subtractArmor: Strength -> Damage
// in DamageSystem
dealDamage: Damage -> () = attack compose subtractArmor compose hurtSomeEntity
Dengan cara ini saya setidaknya menjamin urutan yang benar dari berbagai fungsi yang ditambahkan oleh sistem. Either way, sepertinya saya dengan cepat mendekati pemrograman reaktif fungsional di sini jadi saya bertanya pada diri sendiri apakah saya seharusnya tidak menggunakannya sejak awal (saya baru saja melihat ke FRP, jadi saya mungkin salah di sini). Saya melihat bahwa ECS merupakan peningkatan dari hirarki kelas yang kompleks tetapi saya tidak yakin itu ideal.
Apakah ada solusi untuk ini? Apakah ada fungsi / pola yang saya lewatkan untuk memisahkan ECS dengan lebih bersih? Apakah FRP hanya lebih cocok untuk masalah ini? Apakah masalah ini hanya muncul karena kompleksitas yang melekat pada apa yang saya coba programkan; yaitu apakah FRP akan memiliki masalah yang sama?