Untuk mendapatkan komponen agar dapat memperbarui setiap frame (dan meninggalkan fungsi ini dari komponen yang tidak perlu), saya mendapat ide untuk membuat komponen UpdateComponent. Komponen lain seperti MovableComponent
(yang memiliki kecepatan) akan mewarisi dari IUpdatable
kelas abstrak. Ini memaksa MovableComponent
untuk menerapkan Update(gametime dt)
metode dan lainnya RegisterWithUpdater()
yang memberikan UpdateComponent
pointer ke MovableComponent
. Banyak komponen dapat melakukan ini dan kemudian UpdateComponent
dapat memanggil semua Update(gametime dt)
metode mereka tanpa harus peduli tentang siapa atau apa mereka.
Pertanyaan saya adalah:
- Apakah ini tampak seperti sesuatu yang normal atau digunakan oleh siapa pun? Saya tidak dapat menemukan apa pun tentang masalah ini.
- Bagaimana saya bisa mempertahankan pesanan pada komponen-komponen seperti fisika lalu posisi berubah? Apakah ini perlu?
- Apa cara lain untuk memastikan bahwa komponen yang harus diproses setiap frame sebenarnya diproses?
EDIT
Saya pikir saya akan mempertimbangkan bagaimana memberikan daftar jenis entitas yang dapat diupdate oleh manajer entitas. Kemudian SEMUA komponen jenis itu dapat memperbarui daripada mengaturnya per entitas (yang hanya indeks di sistem saya saja).
Masih. Pertanyaan saya tetap valid bagi saya. Saya tidak tahu apakah ini masuk akal / normal, atau apa yang cenderung dilakukan orang lain.
Juga, orang-orang di Insomniac luar biasa! / EDIT
Kode rebus untuk contoh sebelumnya:
class IUpdatable
{
public:
virtual void Update(float dt) = 0;
protected:
virtual void RegisterAsUpdatable() = 0;
};
class Component
{
...
};
class MovableComponent: public Component, public IUpdatable
{
public:
...
virtual void Update(float dt);
private:
...
virtual void RegisterWithUpdater();
};
class UpdateComponent: public Component
{
public:
...
void UpdateAll();
void RegisterUpdatable(Component* component);
void RemoveUpdatable(Component* component);
private:
...
std::set<Component*> updatables_;
};
sumber
Jawaban:
Salah satu manfaat utama dari sistem komponen adalah kemampuan untuk mengambil keuntungan dari pola caching - icache dan prediksi yang baik karena Anda menjalankan kode yang sama berulang-ulang, dcache yang baik karena Anda dapat mengalokasikan objek dalam kolam yang homogen dan karena vtable, jika apapun, tetap panas.
Cara Anda menyusun komponen Anda, keuntungan ini hilang sepenuhnya, dan pada kenyataannya dapat menjadi kewajiban kinerja dibandingkan dengan sistem berbasis warisan, karena Anda melakukan lebih banyak panggilan virtual dan lebih banyak objek dengan vtable.
Apa yang harus Anda lakukan adalah menyimpan kumpulan per jenis, dan iterasi setiap jenis secara independen untuk melakukan pembaruan.
Ini tidak biasa di permainan besar karena tidak menguntungkan. Ini umum di banyak gim, tetapi secara teknis tidak menarik, jadi tidak ada yang menulis tentang itu.
Kode dalam bahasa seperti C ++ memiliki cara alami untuk memesan eksekusi: ketikkan pernyataan dalam urutan itu.
Pada kenyataannya, itu tidak masuk akal karena tidak ada sistem fisika kuat yang terstruktur seperti itu - Anda tidak dapat memperbarui satu objek fisika tunggal. Alih-alih, kodenya akan lebih mirip:
sumber
Apa yang Anda bicarakan masuk akal dan cukup umum, saya pikir. Ini mungkin memberi Anda informasi lebih lanjut.
sumber
Saya suka pendekatan ini:
Singkatnya: Hindari menjaga perilaku pembaruan dalam komponen. Komponen bukan perilaku. Perilaku (termasuk pembaruan) dapat diimplementasikan dalam beberapa subsistem instance-tunggal. Pendekatan itu mungkin juga membantu untuk batch-proses perilaku serupa untuk banyak komponen (mungkin menggunakan parallel_for atau instruksi SIMD pada data komponen).
Metode IUpdatable dan Pembaruan (gametime dt) tampaknya agak terlalu membatasi dan memperkenalkan penambahan tambahan. Mungkin baik-baik saja jika Anda tidak menggunakan pendekatan subsistem, tetapi jika Anda menggunakannya, maka IUpdatable adalah tingkat hierarki yang berlebihan. Bagaimanapun, MovingSystem harus tahu bahwa ia harus memperbarui Lokasi dan / atau komponen Velocity secara langsung untuk semua entitas yang memiliki komponen ini, sehingga tidak perlu untuk beberapa komponen IUpdatable menengah.
Tetapi Anda dapat menggunakan komponen yang dapat diupdate sebagai mekanisme untuk melewati pembaruan beberapa entitas meskipun mereka memiliki komponen Lokasi dan / atau Kecepatan. Komponen yang dapat diupdate dapat memiliki flag bool yang dapat diatur ke
false
dan yang akan memberi sinyal pada setiap subsistem yang dapat diperbarui yang entitas yang saat ini tidak boleh diperbarui (walaupun dalam konteks seperti itu, Freezable tampaknya lebih sesuai dengan nama untuk komponen).sumber