Setelah membaca beberapa dokumentasi tentang sistem entitas-komponen, saya memutuskan untuk mengimplementasikan tambang. Sejauh ini, saya memiliki kelas Dunia yang berisi entitas dan manajer sistem (sistem), kelas Entitas yang berisi komponen sebagai std :: map, dan beberapa sistem. Saya memegang entitas sebagai std :: vector in World. Tidak masalah sejauh ini. Yang membingungkan saya adalah iterasi entitas, saya tidak dapat memiliki pikiran yang jernih tentang hal itu, jadi saya masih tidak dapat mengimplementasikan bagian itu. Haruskah setiap sistem memiliki daftar entitas lokal yang mereka minati? Atau haruskah saya hanya beralih melalui entitas di kelas Dunia dan membuat loop bersarang untuk beralih melalui sistem dan memeriksa apakah entitas memiliki komponen yang sistem tertarik? Maksudku :
for (entity x : listofentities) {
for (system y : listofsystems) {
if ((x.componentBitmask & y.bitmask) == y.bitmask)
y.update(x, deltatime)
}
}
tapi saya pikir sistem bitmask agak akan memblokir fleksibilitas jika menanamkan bahasa scripting. Atau memiliki daftar lokal untuk setiap sistem akan meningkatkan penggunaan memori untuk kelas. Saya sangat bingung.
sumber
Jawaban:
Ini adalah pertukaran ruang-waktu tradisional .
Sementara iterasi melalui semua entitas dan memeriksa tanda tangan mereka langsung ke kode, itu mungkin menjadi tidak efisien ketika jumlah sistem Anda tumbuh - bayangkan sistem khusus (biarkan input) yang mencari entitas tunggal yang mungkin menarik di antara ribuan entitas yang tidak terkait .
Yang mengatakan, pendekatan ini mungkin masih cukup baik tergantung pada tujuan Anda.
Meskipun, jika Anda khawatir tentang kecepatan, tentu saja ada solusi lain untuk dipertimbangkan.
Persis. Ini adalah pendekatan standar yang harus memberi Anda kinerja yang layak dan cukup mudah untuk diterapkan. Overhead memori dapat diabaikan menurut pendapat saya - kita berbicara tentang menyimpan pointer.
Sekarang bagaimana mempertahankan "daftar minat" ini mungkin tidak terlalu jelas. Adapun wadah data,
std::vector<entity*> targets
kelas sistem di dalam cukup sempurna. Sekarang yang saya lakukan adalah ini:Setiap kali saya menambahkan komponen ke entitas:
iterate melalui semua sistem dunia dan jika ada sistem yang tanda tangannya tidak cocok dengan tanda tangan entitas saat ini dan tidak cocok dengan tanda tangan baru, itu menjadi jelas kita harus mendorong kembali pointer ke entitas kita di sana.
Menghapus entitas sepenuhnya analog, dengan satu-satunya perbedaan yang kami hapus jika suatu sistem cocok dengan tanda tangan kami saat ini (yang berarti bahwa entitas itu ada di sana) dan tidak cocok dengan tanda tangan baru (yang berarti entitas seharusnya tidak lagi berada di sana ).
Sekarang Anda mungkin mempertimbangkan penggunaan std :: list karena menghapus dari vektor adalah O (n), tidak menyebutkan bahwa Anda harus menggeser sebagian besar data setiap kali Anda menghapus dari tengah. Sebenarnya, Anda tidak harus - karena kami tidak peduli tentang pemrosesan pesanan pada tingkat ini, kami hanya dapat memanggil std :: remove dan hidup dengan kenyataan bahwa pada setiap penghapusan kami hanya perlu melakukan O (n) mencari kami entitas yang akan dihapus.
std :: list akan memberi Anda O (1) hapus tetapi di sisi lain Anda memiliki sedikit overhead memori tambahan. Juga ingat bahwa sebagian besar waktu Anda akan memproses entitas dan tidak menghapusnya - dan ini pasti dilakukan lebih cepat menggunakan std :: vector.
Jika Anda sangat kritis terhadap kinerja, Anda dapat mempertimbangkan pola pengaksesan data lain , tetapi bagaimanapun Anda mempertahankan semacam "daftar minat". Ingat juga bahwa jika Anda menjaga abstrak Entity System API Anda seharusnya tidak menjadi masalah untuk meningkatkan metode pemrosesan entitas sistem jika framerate Anda turun karena mereka - jadi untuk sekarang, pilih metode yang paling mudah bagi Anda untuk membuat kode - hanya kemudian profil dan tingkatkan jika perlu.
sumber
Ada pendekatan yang layak dipertimbangkan di mana setiap sistem memiliki komponen yang terkait dengan dirinya sendiri dan entitas hanya merujuk kepada mereka. Pada dasarnya, kelas Anda (disederhanakan)
Entity
terlihat seperti ini:Ketika Anda mengatakan
RigidBody
komponen yang dilampirkan padaEntity
, Anda memintanya dariPhysics
sistem Anda . Sistem menciptakan komponen dan membiarkan entitas menyimpan pointer ke sana. Sistem Anda kemudian terlihat seperti:Sekarang, ini mungkin terlihat sedikit kontra intuitif pada awalnya tetapi keuntungannya terletak pada cara sistem entitas komponen memperbarui keadaan mereka. Seringkali, Anda akan mengulangi melalui sistem Anda dan meminta mereka memperbarui komponen terkait
Kekuatan memiliki semua komponen yang dimiliki oleh sistem dalam memori yang berdekatan adalah bahwa ketika sistem Anda mengulangi setiap komponen dan memutakhirkannya, pada dasarnya hanya perlu dilakukan
Itu tidak harus mengulangi semua entitas yang berpotensi tidak memiliki komponen yang mereka perlu perbarui dan juga berpotensi untuk kinerja cache yang sangat baik karena semua komponen akan disimpan secara bersamaan. Ini adalah satu, jika bukan keuntungan terbesar dari metode ini. Anda akan sering memiliki ratusan dan ribuan komponen pada waktu tertentu, mungkin juga mencoba dan tampil sebaik mungkin.
Pada titik itu
World
hanya loop Anda melalui sistem dan memanggilupdate
mereka tanpa perlu mengulangi entitas juga. Ini (imho) desain yang lebih baik karena dengan begitu tanggung jawab sistem jauh lebih jelas.Tentu saja, ada segudang desain seperti itu sehingga Anda harus hati-hati mengevaluasi kebutuhan gim Anda dan memilih yang paling tepat, tetapi seperti yang bisa kita lihat di sini, terkadang detail desain kecillah yang dapat membuat perbedaan.
sumber
Menurut pendapat saya, arsitektur yang baik adalah membuat lapisan komponen dalam entitas, dan memisahkan manajemen setiap sistem di lapisan komponen ini. Sebagai contoh, sistem logika memiliki beberapa komponen logika yang mempengaruhi entitas mereka, dan menyimpan atribut umum yang dibagi ke semua komponen di entitas.
Setelah itu, jika Anda ingin mengelola objek masing-masing sistem di titik yang berbeda, atau dalam urutan tertentu, lebih baik untuk membuat daftar komponen aktif di setiap sistem. Semua daftar petunjuk yang dapat Anda buat dan kelola dalam sistem kurang dari satu sumber daya yang dimuat.
sumber