Memproses masalah kumpulan komponen - Subsistem Entitas

8

Deskripsi arsitektur

Saya membuat (mendesain) sistem entitas dan saya mengalami banyak masalah. Saya berusaha menjaganya agar tetap Berorientasi Data dan seefisien mungkin. Komponen saya adalah struktur POD (array byte yang tepat) yang dialokasikan dalam kumpulan yang homogen. Setiap kumpulan memiliki ComponentDescriptor - hanya berisi nama komponen, tipe bidang dan nama bidang.

Entity hanyalah pointer ke array komponen (di mana alamat bertindak seperti ID entitas). EntityPrototype berisi nama entitas dan array nama komponen. Akhirnya Subsistem (Sistem atau Prosesor) yang berfungsi pada kumpulan komponen.

Masalah aktual

Masalahnya adalah bahwa beberapa komponen bergantung pada orang lain (Model, Sprite, PhysicalBody, Animation tergantung pada Transform komponen) yang membuat banyak masalah ketika datang untuk memprosesnya.

For example, lets define some entities using [S]prite, [P]hysicalBody and [H]ealth:
Tank:   Transform, Sprite, PhysicalBody
BgTree: Transform, Sprite
House:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
PPPP        // PhysicalBody pool
HH          // Health component

Tidak ada cara untuk memprosesnya menggunakan indeks. Saya menghabiskan 3 hari mengerjakannya dan saya masih belum punya ide. Dalam desain sebelumnya TransformComponent terikat dengan entitas - tetapi itu bukan ide yang baik. Bisakah Anda memberi saya beberapa saran bagaimana memprosesnya? Atau mungkin saya harus mengubah desain keseluruhan? Mungkin saya harus membuat kumpulan entites (kumpulan komponen pool) - tapi saya kira itu akan menjadi mimpi buruk bagi cache CPU.

Terima kasih

mani3xis
sumber
Multiplayer? (Ini relevan)
Jonathan Dickinson

Jawaban:

2

Penafian: Murni keluar dari pengetahuan kelas sistem saya.

Saya awalnya berpikir, mengapa tidak menggunakan fungsi hash pada ID entitas untuk indeks Anda?

Dengan begitu Anda akan mendapatkannya

T[A]nk:   Transform, Sprite, PhysicalBody
B[G]Tree: Transform, Sprite
H[O]use:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

OGAGAGGOGGG // Entity pool (letters corresopnding to entity type)
TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
P P P  P    // PhysicalBody pool
H      H    // Health component

Atau bagaimanapun entitas itu ditempatkan. Anda bisa memiliki kumpulan untuk semua komponen dan entitas dan menggunakan kumpulan entitas sebagai "master," sehingga tabrakan diperiksa terhadap array entitas. Tapi tentu saja Anda mendapatkan masalah komponen dan entitas daur ulang.

Jika desain game Anda memungkinkan, Anda bisa merencanakan ke depan di mana setiap jenis entitas berjalan sehingga Anda bisa mendapatkan pengemasan yang seefisien mungkin. Say entitas 0-20 dicadangkan untuk tank, entitas 21-30 untuk rumah, dan 31-60 untuk BGTrees. Anda mungkin tidak dapat menelurkan baddos tak terbatas secara efisien, dan agak mengalahkan dinamisme sistem komponen, tetapi itu akan menyelesaikan masalah. Saya tidak melihat cara untuk memiliki kue Anda dan memakannya juga.

Saya sedang memikirkan cara-cara untuk mungkin mempercepat render pass di mana Anda memiliki RenderingComponentyang berisi semua data yang dibutuhkan oleh sistem render sehingga hanya dapat menerobos serangkaian hal-hal ini, tetapi kemudian ada overhead untuk menyalin data. Juga, setiap kali Anda melakukan dereferensi pointer Anda berpikir apakah itu masih dalam cache atau tidak.

Jika Anda menginginkan game super cepat, saya akan mengatakan rencanakan alokasi Anda. Jika Anda menginginkan arsitektur game yang fleksibel, gulirkan hashtable dan string ID. Kapan pun Anda menginginkan fleksibilitas, Anda perlu membangun abstraksi, dan karenanya akan mengeluarkan biaya tambahan.

TL; DR;
Berdasarkan apa yang Anda jelaskan, saya akan membuat level yang lebih tinggi RenderComponentdengan pointer ke Spritedan Transformkomponen dan memberikan referensi yang diperlukan ketika Anda menginisialisasi entitas.

(Permintaan maaf untuk segala yang dianggap mengoceh, saya telah memikirkan hal ini dalam sistem saya juga, jadi ini adalah kesempatan untuk memikirkannya)

michael.bartnett
sumber
Saya tidak tahu apakah peta hash sangat efektif. Saya ingin memiliki sistem entitas di mana subsistem berisi fungsi DOD seperti: void update(u32 n, PhysicalBodyComponents* bodys, Transform* transforms)Saya ingin bekerja pada banyak input dan membagi fungsi ini pada banyak core. Apakah mungkin dengan hashmaps?
mani3xis
Peta hash hanyalah cara untuk mengidentifikasi hubungan antara entitas dan komponen. Ini tergantung pada bagaimana game Anda diatur, tetapi saya tidak melihat cara yang efisien untuk menjamin bahwa array Anda bodysdan transformsakan berbaris. Ini adalah sesuatu yang tidak dapat Anda atasi tanpa menambahkan lapisan abstraksi atau merencanakan alokasi Anda. Saya merasa tidak memiliki keahlian untuk berbicara tentang penskalaan ke beberapa core. Mungkin menemukan pertanyaan tentang threading dan scaling atau tulis sendiri.
michael.bartnett
Penskalaan mudah ketika fungsi bekerja pada array linier - Saya dapat mengatur rentang untuk setiap inti dan menjalankannya. Itulah sebabnya saya mencoba menghindari hashmaps. Saya akan mencoba mendesain ulang sistem entitas ini. Saya harus benar-benar berhati-hati dengan cache yang hilang - PS2 memiliki RAM yang sangat terbatas, dll. BTW: Tidak ada yang mustahil :)
mani3xis
Tidak ada yang mustahil, tetapi tidak semuanya layak;). Anda dapat mengusahakan kesederhanaan dan keanggunan implementasi, kecepatan eksekusi, dan konsumsi memori: pilih dua. Ketika Anda menemukan solusi Anda, silakan posting sebagai jawaban saya yakin saya bukan satu-satunya yang ingin melihatnya.
michael.bartnett