Saya mencoba merancang sistem entitas berbasis komponen untuk tujuan pembelajaran (dan kemudian digunakan pada beberapa game) dan saya mengalami beberapa masalah ketika memperbarui status entitas.
Saya tidak ingin memiliki metode pembaruan () di dalam Komponen untuk mencegah dependensi antara Komponen.
Apa yang saya pikirkan saat ini adalah bahwa komponen menyimpan data dan komponen pembaruan sistem.
Jadi, jika saya memiliki permainan 2D sederhana dengan beberapa entitas (misalnya pemain, musuh1, musuh2) yang memiliki komponen Transform, Movement, State, Animation dan Rendering, saya pikir saya harus memiliki:
- Suatu MovementSystem yang menggerakkan semua komponen Gerakan dan memperbarui komponen Negara
- Dan RenderSystem yang memperbarui komponen Animasi (komponen animasi harus memiliki satu animasi (yaitu seperangkat bingkai / tekstur) untuk setiap negara bagian dan memperbarui itu berarti memilih animasi yang sesuai dengan keadaan saat ini (misalnya melompat, bergerak, bergerak, dll), dan memperbarui indeks bingkai). Kemudian, RenderSystem memperbarui komponen Render dengan tekstur yang sesuai dengan bingkai saat ini dari masing-masing entitas Animasi dan menampilkan semuanya di layar.
Saya telah melihat beberapa implementasi seperti kerangka kerja Artemis, tapi saya tidak tahu bagaimana menyelesaikan situasi ini:
Katakanlah permainan saya memiliki entitas berikut. Setiap entitas memiliki serangkaian negara dan satu animasi untuk setiap negara:
- pemain: "idle", "moving_right", "jumping"
- musuh1: "moving_up", "moving_down"
- musuh2: "moving_left", "moving_right"
Apa pendekatan yang paling diterima untuk memperbarui keadaan saat ini dari setiap entitas? Satu-satunya hal yang dapat saya pikirkan adalah memiliki sistem yang terpisah untuk setiap kelompok entitas dan komponen Negara dan Animasi terpisah sehingga saya akan memiliki PlayerState, PlayerAnimation, Enemy1State, Enemy1Animation ... PlayerMovementSystem, PlayerRenderingSystem ... tapi saya pikir ini buruk solusi dan mematahkan tujuan memiliki sistem berbasis komponen.
Seperti yang Anda lihat, saya sangat tersesat di sini, jadi saya sangat menghargai bantuan apa pun.
EDIT: Saya pikir solusi untuk membuat ini berfungsi seperti yang saya inginkan adalah yang ini:
Anda membuat komponen statistik dan komponen animasi cukup umum untuk digunakan untuk semua entitas. Data yang dikandungnya akan menjadi pengubah untuk mengubah hal-hal seperti animasi yang dimainkan atau yang menyatakan tersedia. - Byte56
Sekarang, saya mencoba mencari cara untuk mendesain 2 komponen ini cukup umum sehingga saya dapat menggunakannya kembali. Mungkinkah memiliki UID untuk setiap negara bagian (mis. Berjalan, berlari ...) dan menyimpan animasi di peta ke dalam AnimationComponent yang dikunci oleh pengenal ini menjadi solusi yang baik?
sumber
statecomponent
dananimationcomponent
cukup umum untuk digunakan untuk semua entitas. Data yang dikandungnya akan menjadi pengubah untuk mengubah hal-hal seperti animasi yang dimainkan atau yang menyatakan tersedia.Jawaban:
IMHO
Movement
komponen harus menahan keadaan saat ini (Movement.state
) danAnimation
komponen harus mengamati perubahanMovement.state
dan memperbarui animasi saat ini (Animation.animation
) sesuai, dengan menggunakan pencarian sederhana status id ke animasi (seperti yang disarankan pada akhir OP). Jelas ini berartiAnimation
akan tergantung padaMovement
.Struktur alternatif adalah memiliki
State
komponen generik , yangAnimation
mengamati, danMovement
memodifikasi, yang pada dasarnya adalah model-view-controller (state-animation-movement dalam kasus ini).Alternatif lain adalah meminta entitas mengirimkan suatu peristiwa ke komponennya ketika statusnya berubah.
Animation
akan mendengarkan acara ini dan memperbarui animasinya sesuai. Ini menghilangkan ketergantungan, meskipun Anda bisa berpendapat bahwa versi dependen adalah desain yang lebih transparan.Semoga berhasil.
sumber
Movement
akan mengontrolState
(tidak mengamati). Kasus terakhir: YaMovement
akan melakukannyaentity.dispatchEvent(...);
atau lebih, dan semua komponen lain yang mendengarkan acara semacam itu akan menerimanya. Kinerja tentu saja lebih buruk daripada pemanggilan metode murni, tetapi tidak banyak. Anda dapat menggabungkan objek acara misalnya. Namun, Anda tidak harus menggunakan entitas sebagai "simpul acara", Anda juga bisa menggunakan "bus peristiwa" khusus, sehingga kelas entitas Anda sepenuhnya tidak ada di dalamnya.Tentang masalah Anda, jika NEGARA hanya digunakan dalam Animasi, maka Anda bahkan tidak perlu mengungkapkannya ke Komponen lain. Jika memiliki lebih dari satu penggunaan, maka Anda perlu memaparkannya.
Sistem Komponen / Subsistem yang Anda gambarkan terasa lebih berbasis hierarki daripada berbasis komponen. Bagaimanapun, apa yang Anda gambarkan sebagai komponen sebenarnya adalah struktur data. Itu tidak berarti itu adalah sistem yang buruk, hanya saja saya tidak berpikir itu cocok dengan pendekatan berbasis komponen dengan baik.
Seperti yang Anda catat, dependensi adalah masalah besar dalam sistem berbasis komponen. Ada berbagai cara untuk menghadapinya. Beberapa memerlukan setiap komponen untuk menyatakan dependensi mereka dan melakukan pemeriksaan ketat. Pertanyaan lain untuk komponen yang mengimplementasikan antarmuka spesifik. Yang lain meneruskan referensi ke komponen dependen ketika mereka instantiate masing-masing.
Secara independen dari metode yang Anda gunakan, Anda akan membutuhkan semacam GameObject untuk bertindak sebagai kumpulan Komponen. Apa yang disediakan GameObject dapat sangat bervariasi dan Anda dapat menyederhanakan dependensi antar-komponen dengan mendorong beberapa data yang sering digunakan ke level GameObject. Unity melakukan itu dengan transformasi misalnya, memaksa semua objek game untuk memilikinya.
Mengenai masalah yang Anda minta dari berbagai negara / animasi untuk objek game yang berbeda, inilah yang akan saya lakukan. Pertama, saya tidak akan terlalu suka pada tahap implementasi ini: hanya terapkan apa yang Anda butuhkan sekarang untuk membuatnya bekerja, kemudian tambahkan bel dan peluit saat Anda membutuhkannya.
Jadi, saya akan mulai dengan komponen 'Status': PlayerStateComponent, Enemy1State, Enemy2State. Komponen negara akan mengurus perubahan negara pada waktu yang tepat. Status adalah sesuatu yang hampir semua objek Anda miliki, sehingga dapat berada di GameObject.
Lalu, akan ada AnimationCompoment. Ini akan memiliki kamus animasi yang dikunci untuk negara bagian. Di pembaruan (), ubah animasi jika keadaan berubah.
Ada artikel bagus tentang membangun kerangka kerja yang tidak bisa saya temukan. Dikatakan bahwa ketika Anda tidak memiliki pengalaman dalam domain, Anda harus memilih satu masalah dan melakukan implementasi paling sederhana yang menyelesaikan masalah saat ini . Kemudian Anda menambahkan masalah / kasus penggunaan lain dan memperluas kerangka saat Anda melanjutkan, sehingga tumbuh secara organik. Saya sangat suka pendekatan itu, terutama ketika bekerja dengan konsep baru seperti yang Anda lakukan.
Implementasi yang saya usulkan cukup naif, tetapi di sini ada beberapa kemungkinan perbaikan saat Anda menambahkan lebih banyak use-case:
sumber
Selain jawaban ADB Anda dapat menggunakan http://en.wikipedia.org/wiki/Dependency_injection , yang membantu ketika Anda perlu membangun banyak komponen dengan mengirimkannya sebagai referensi ke konstruktor mereka. Jelas mereka masih akan saling bergantung (jika itu diperlukan dalam basis kode Anda), tetapi Anda dapat meletakkan semua ketergantungan itu di satu tempat di mana dependensi diatur dan sisa kode Anda tidak perlu tahu tentang dependensi.
Pendekatan ini juga bekerja dengan baik jika Anda menggunakan antarmuka karena setiap kelas komponen hanya meminta apa yang dibutuhkan atau di mana ia perlu terdaftar dan hanya kerangka kerja injeksi ketergantungan (atau tempat di mana Anda mengatur semuanya, biasanya aplikasi) tahu tentang siapa yang butuh apa .
Untuk sistem sederhana, Anda mungkin lolos tanpa menggunakan DI atau kode bersih, kelas RenderingSystem Anda terdengar seperti Anda perlu memanggilnya secara statis atau setidaknya membuatnya tersedia di setiap komponen, yang cukup banyak membuat mereka saling bergantung dan sulit untuk diubah. Jika Anda tertarik pada pendekatan yang lebih bersih, periksa tautan DI wiki di atas dan bacalah tentang Clean Code: http://clean-code-developer.com/
sumber