Setelah mengajukan dua pertanyaan tentang sistem entitas ( 1 , 2 ), dan membaca beberapa artikel tentang mereka, saya pikir saya memahaminya jauh lebih baik daripada sebelumnya. Saya masih memiliki beberapa ketidakpastian, terutama tentang membangun emitor partikel, sistem input, dan kamera. Saya jelas masih memiliki beberapa masalah dalam memahami sistem entitas, dan mereka mungkin berlaku untuk berbagai objek, tetapi saya memilih tiga karena mereka konsep yang sangat berbeda, harus mencakup tanah yang cukup luas, dan membantu saya memahami sistem entitas dan cara menangani masalah seperti ini, saya sendiri, ketika mereka datang
Saya sedang membangun sebuah mesin dalam JavaScript, dan saya telah mengimplementasikan sebagian besar fitur inti, yang meliputi: penanganan input, sistem animasi fleksibel, penghasil partikel, kelas matematika dan fungsi, penanganan adegan, kamera dan render, dan sejumlah besar dari hal-hal lain yang biasanya didukung oleh mesin. Saya membaca jawaban Byte56, yang membuat saya tertarik membuat mesin menjadi sistem entitas. Itu masih tetap mesin game HTML5, dengan filosofi adegan dasar, tetapi harus mendukung penciptaan entitas yang dinamis dari komponen.
Masalah yang saya miliki, sekarang, adalah menyesuaikan konsep mesin lama saya ke dalam paradigma pemrograman baru ini. Ini adalah beberapa definisi dari pertanyaan sebelumnya, yang diperbarui:
Sebuah Entity adalah sebuah identifier. Itu tidak memiliki data, itu bukan objek, ini adalah id sederhana yang mewakili indeks dalam daftar adegan semua entitas (yang sebenarnya saya rencanakan untuk diimplementasikan sebagai matriks komponen).
Sebuah Komponen adalah pemegang data, tetapi dengan metode yang dapat beroperasi pada data tersebut. Contoh terbaik adalah
Vector2D
komponen, atau "Posisi". Memiliki data:x
dany
, tetapi juga beberapa metode yang membuat operasi pada data sedikit lebih mudah:add()
,normalize()
, dan sebagainya.Sebuah Sistem adalah sesuatu yang dapat beroperasi pada set entitas yang memenuhi persyaratan tertentu; biasanya entitas perlu memiliki serangkaian komponen tertentu, untuk dioperasikan. Sistem adalah bagian "logika", bagian "algoritma", semua fungsi yang disediakan oleh komponen murni untuk memudahkan pengelolaan data.
Kamera
Kamera memiliki Vector2D
properti posisi, properti rotasi, dan beberapa metode untuk memusatkannya di sekitar titik. Setiap bingkai, diumpankan ke penyaji, bersama dengan adegan, dan semua objek diterjemahkan sesuai dengan posisinya. Adegan kemudian ditampilkan.
Bagaimana saya bisa mewakili objek semacam ini dalam sistem entitas? Apakah kamera akan menjadi entitas, komponen, atau kombinasi (sesuai jawaban saya )?
Emitor Partikel
Masalah yang saya miliki dengan penghasil partikel adalah, sekali lagi, apa yang seharusnya. Saya cukup yakin bahwa partikel itu sendiri tidak harus menjadi entitas, karena saya ingin mendukung lebih dari 10.000 dari mereka, dan saya percaya bahwa menciptakan banyak entitas akan menjadi pukulan berat pada kinerja saya.
Bagaimana saya bisa mewakili objek semacam ini dalam sistem entitas?
Manajer Input
Yang terakhir yang ingin saya bicarakan adalah bagaimana input harus ditangani. Dalam versi mesin saya saat ini, ada kelas yang disebut Input
. Ini adalah penangan yang berlangganan acara browser, seperti penekanan tombol dan perubahan posisi mouse, dan juga mempertahankan keadaan internal. Kemudian, kelas pemain memiliki react()
metode, yang menerima objek input sebagai argumen. Keuntungan dari ini adalah bahwa objek input dapat diserialisasi ke .JSON, dan kemudian dibagikan melalui jaringan, memungkinkan untuk simulasi multipemain yang mulus.
Bagaimana ini diterjemahkan ke dalam sistem entitas?
Inilah cara saya mendekati ini:
Kamera
Kamera saya adalah entitas seperti yang lainnya, yang memiliki komponen yang terpasang:
Transform
memilikiTranslation
,Rotation
danScale
properti, selain yang lain untuk kecepatan, dll.Pov
(Sudut pandang) telahFieldOfView
,AspectRatio
,Near
,Far
, dan hal lain yang diperlukan untuk menghasilkan matriks proyeksi, di sampingIsOrtho
bendera yang digunakan untuk beralih antara perspektif dan proyeksi ortografi.Pov
juga menyediakan properti lazy-load yangProjectionMatrix
digunakan oleh sistem rendering yang dihitung secara internal saat dibaca, dan di-cache hingga salah satu properti lainnya dimodifikasi.Tidak ada sistem kamera khusus. Sistem Render menyimpan daftar
Pov
's dan berisi logika untuk menentukan mana yang akan digunakan saat rendering.Memasukkan
Sebuah
InputReceiver
komponen dapat melekat pada entitas apapun. Ini memiliki pengendali kejadian yang terlampir (atau lambda jika bahasa Anda mendukungnya) yang digunakan untuk menahan pemrosesan input khusus entitas, yang mengambil parameter untuk keadaan tombol saat ini dan sebelumnya, lokasi mouse saat ini dan keadaan tombol dan keadaan tombol, dll. (Sebenarnya, ada penangan terpisah untuk mouse dan keyboard).Misalnya, dalam game uji mirip Asteroid yang saya buat ketika terbiasa dengan Entity / Component, saya memiliki dua metode input lambda. Satu menangani navigasi kapal dengan memproses tombol panah dan bilah ruang (untuk menembak). Yang lain menangani input keyboard umum - tombol untuk keluar, jeda, dll, me-restart level, dll. Saya membuat dua komponen, melampirkan masing-masing lambda ke komponennya sendiri, kemudian menetapkan komponen penerima navigasi ke entitas kapal, yang lain ke entitas pemroses perintah yang tidak terlihat.
Inilah pengendali acara untuk menangani kunci yang dipegang di antara frame yang terhubung ke
InputReceiver
komponen kapal (C #):Jika kamera Anda mobile, memberikan sendiri
InputReceiver
danTransform
komponen, melampirkan lambda atau handler yang mengimplementasikan apa pun jenis kontrol yang Anda inginkan, dan Anda sudah selesai.Ini agak rapi karena Anda dapat memindahkan
InputReceiver
komponen dengan pengendali navigasi yang terpasang dari kapal ke asteroid, atau yang lainnya, dan menerbangkannya. Atau, dengan menetapkanPov
komponen ke hal lain dalam adegan Anda - asteroid, lampu jalan, dll. - Anda dapat melihat pemandangan Anda dari perspektif entitas itu.Sebuah
InputSystem
kelas yang mempertahankan keadaan internal untuk keyboard, mouse, dllInputSystem
menyaring koleksi entitas internal untuk entitas yang memilikiInputReceiver
komponen. DalamUpdate()
metodenya, iterates melalui koleksi itu dan memanggil input handler yang melekat pada masing-masing komponen dengan cara yang sama seperti sistem rendering menarik setiap entitas dengan suatuRenderable
komponen.Partikel
Ini benar-benar tergantung pada bagaimana Anda berencana berinteraksi dengan partikel. Jika Anda hanya membutuhkan sistem partikel yang berperilaku seperti satu objek - katakanlah, kembang api menunjukkan bahwa pemain tidak dapat menyentuh atau memukul - maka saya akan membuat entitas tunggal, dan
ParticleRenderGroup
komponen yang berisi informasi apa pun yang Anda butuhkan untuk partikel - pembusukan, dll. - yang tidak tercakup olehRenderable
komponen Anda . Saat merender, sistem render akan melihat apakah suatu entitas memilikiRenderParticleGroup
lampiran dan menanganinya sesuai.Jika Anda membutuhkan partikel individu untuk berpartisipasi dalam deteksi tumbukan, merespons masukan, dll., Tetapi Anda hanya ingin menjadikannya sebagai kumpulan, saya akan membuat
Particle
komponen yang berisi informasi tersebut berdasarkan per-partikel, dan membuatnya sebagai entitas yang terpisah. Sistem render masih dapat mengelompokkannya, tetapi mereka akan diperlakukan sebagai objek yang terpisah oleh sistem lain. (Ini bekerja sangat baik dengan instancing.)Kemudian, baik di
MotionSystem
(atau apa pun yang Anda gunakan yang menangani memperbarui posisi entitas, dll.) Atau dalam dedikasiParticleSystem
, lakukan pemrosesan apa pun yang diperlukan untuk setiap partikel per-bingkai. ItuRenderSystem
akan bertanggung jawab untuk membangun / mengumpulkan dan menyimpan koleksi partikel saat mereka dibuat dan dihancurkan, dan membuatnya sesuai kebutuhan.Satu hal yang menyenangkan tentang pendekatan ini adalah Anda tidak perlu memiliki kasus khusus untuk tabrakan, pemusnahan, dll untuk partikel; mereka kode yang Anda tulis untuk setiap jenis entitas lain masih dapat digunakan.
Kesimpulan
Jika Anda mempertimbangkan untuk melakukan lintas-platform - tidak berlaku super untuk JavaScript - semua kode khusus platform Anda (yaitu rendering dan input) diisolasi ke dalam dua sistem. Logika gim Anda tetap berada di kelas platform-agnosit (gerakan, tabrakan, dll.) Sehingga Anda tidak perlu menyentuhnya saat porting.
Saya mengerti dan setuju dengan posisi Sean bahwa hal-hal yang berhubungan dengan sepatu menjadi suatu pola untuk benar-benar mengikuti pola itu, daripada mengubah pola untuk memenuhi kebutuhan aplikasi Anda, itu buruk. Saya hanya tidak melihat apa pun di Input, Kamera atau Partikel yang memerlukan perlakuan semacam itu.
sumber
Input dan logika game kemungkinan akan ditangani dalam kode khusus di luar sistem komponen entitas. Secara teknis dimungkinkan untuk memasukkannya ke dalam desain, tetapi ada sedikit manfaatnya - logika permainan dan UI berantakan dan penuh abstraksi bocor tidak peduli apa yang Anda lakukan, dan mencoba untuk memaksa pasak persegi ke dalam lubang bundar hanya karena kemurnian arsitektur adalah pemborosan waktu.
Demikian juga, penghasil partikel adalah binatang buas khusus, terutama jika Anda benar-benar peduli tentang kinerja. Komponen emitor masuk akal, tetapi grafik akan melakukan beberapa sihir khusus dengan komponen-komponen itu, dicampur dengan sihir selama rendering lainnya.
Mengenai kamera Anda, cukup beri kamera bendera yang aktif dan mungkin indeks "kedalaman", dan biarkan sistem grafis membuat semuanya yang diaktifkan. Ini sebenarnya berguna untuk banyak trik, termasuk GUI (ingin GUI Anda dirender dalam mode ortografis di atas dunia game? Tidak masalah, mereka hanya dua kamera dengan topeng objek berbeda dan GUI diatur ke lapisan yang lebih tinggi). Ini juga berguna untuk lapisan efek khusus dan semacamnya.
sumber
Saya tidak yakin apa pertanyaan ini sebenarnya. Mengingat bahwa satu-satunya hal yang Anda miliki dalam permainan adalah entitas, maka kamera harus menjadi entitas. Fungsi kamera diimplementasikan melalui semacam komponen kamera. Jangan memiliki komponen "Posisi" dan "Rotasi" yang terpisah - yang terlalu rendah. Mereka harus digabungkan menjadi semacam komponen WorldPosition yang akan berlaku untuk setiap entitas yang terletak di dunia. Adapun yang harus digunakan ... Anda harus mendapatkan logika ke dalam sistem entah bagaimana. Entah Anda menyandikannya ke dalam sistem penanganan kamera Anda, atau Anda melampirkan skrip, atau sesuatu. Anda dapat memiliki bendera yang diaktifkan / dinonaktifkan pada komponen kamera jika itu membantu.
Saya juga. Sebuah emitor partikel akan menjadi entitas, dan sistem partikel akan melacak partikel yang terkait dengan entitas yang diberikan. Hal-hal seperti ini adalah di mana Anda menyadari bahwa "semuanya adalah entitas" bukan kepalang yang tidak praktis. Dalam praktiknya, satu-satunya hal yang merupakan entitas adalah objek yang relatif kompleks yang mendapat manfaat dari kombinasi komponen.
Adapun Input: input tidak ada di dunia game seperti itu sehingga ditangani oleh suatu sistem. Belum tentu 'sistem komponen' karena tidak semua yang ada di gim Anda akan berputar di sekitar komponen. Tetapi akan ada sistem input. Anda mungkin ingin menandai entitas yang merespons input dengan semacam komponen Player, tetapi inputnya akan kompleks dan sepenuhnya spesifik game sehingga tidak ada gunanya mencoba membuat komponen untuk ini.
sumber
Inilah beberapa ide saya untuk menyelesaikan masalah ini. Mereka mungkin akan memiliki sesuatu yang salah dengan mereka, dan mungkin akan ada pendekatan yang lebih baik, jadi tolong, arahkan saya kepada mereka yang menjawab!
Kamera :
Ada komponen "Kamera", yang dapat ditambahkan ke entitas apa pun. Saya tidak dapat benar-benar mengetahui data apa yang harus saya masukkan ke dalam komponen ini: saya dapat memisahkan komponen "Posisi" dan "Rotasi"! The
follow
metode tidak perlu dilaksanakan, karena sudah mengikuti entitas itu melekat! Dan saya bebas untuk memindahkannya. Masalah dengan sistem ini akan banyak objek kamera yang berbeda: bagaimana bisaRendererSystem
tahu mana yang harus digunakan? Dan juga, saya dulu hanya melewati objek kamera, tetapi sekarang tampaknyaRendererSystem
kebutuhan untuk beralih dua kali dari semua entitas: pertama untuk menemukan yang bertindak seperti kamera, dan kedua, untuk benar-benar membuat semuanya.ParticleEmitter :
Akan ada
ParticleSystem
yang akan memperbarui semua entitas yang memiliki komponen "Emitter". Partikel adalah benda bodoh dalam ruang koordinat relatif, di dalam komponen itu. Ada masalah render di sini: Saya perlu membuatParticleRenderer
sistem, atau memperluas fungsionalitas yang sudah ada.Sistem input :
Perhatian utama bagi saya di sini adalah logika, atau
react()
metode. Satu-satunya solusi yang saya temukan adalah sistem terpisah untuk itu, dan komponen untuk setiap sistem, yang akan menunjukkan mana yang akan digunakan. Ini benar-benar terlihat terlalu berantakan, dan saya tidak tahu bagaimana cara menanganinya dengan baik. Satu hal adalah, selama saya khawatir,Input
bisa tetap diimplementasikan sebagai kelas, tetapi saya tidak melihat bagaimana saya bisa mengintegrasikannya ke sisa permainan.sumber