Saya cukup baru dalam pengembangan game (tetapi tidak untuk pemrograman) dan saya mencoba mencari tahu apa yang akan menjadi cara terbaik untuk menangani komunikasi antar-dunia. Maksud saya adalah ini:
Saya telah membaca tentang sistem komponen entitas (ECS) dan bagaimana orang menyarankan menggunakan dunia / spasi yang berbeda ( http://gamedevelopment.tutsplus.com/tutorials/spaces-useful-game-object-containers--gamedev-14091 ) untuk subbagian dari game. Misalnya HUD, inventaris atau pertempuran / pergerakan masing-masing mendapatkan dunia / ruang yang terpisah (karena mereka memiliki grafik dan logika yang berbeda.
Namun, saya bertanya-tanya bagaimana inventaris, atau HUD tahu tentang kesehatan pemain ketika kesehatan ditangani oleh ruang / dunia yang berbeda, misalnya ketika dalam pertempuran?
Ini juga berlaku untuk perkembangan game secara umum, misalnya dialog dengan NPC (dialog akan menjadi ruang terpisah karena itu adalah layar popup) tetapi bagaimana Anda akan menyampaikan pilihan yang dibuat dalam (atau keadaan) dialog ke ruang / dunia lain . Atau pada dasarnya semua jenis acara lain yang memengaruhi perkembangan game di berbagai ruang / dunia (kesehatan, mana, pencarian, dialog, pertarungan, inventaris, hud, dll.)
Bagaimana seseorang menangani desain seperti ini? Apakah perlu objek tunggal (dalam implementasi) yang menampung semua jenis informasi ini? Itu akan aneh karena dengan demikian components
kebutuhan untuk menyampaikan setiap perubahan pada objek tunggal ini yang terasa seperti melakukan hal-hal dua kali (bertentangan dengan KERING utama pemrograman) ...
Saya agak bingung di sini dalam hal desain, ada petunjuk?
--- EDIT ---
Jadi saya sudah membaca beberapa posting lain yang disarankan oleh komentar dan mendapat ide umum tentang kemungkinan, namun masing-masing dari mereka tampaknya memiliki satu kelemahan utama yang membuat mereka tidak benar. Sangat mungkin bahwa saya mengawasi detail yang akan menyelesaikan kelemahan ini, jadi silakan koreksi saya. Saya akan mencoba memberikan ikhtisar serta beberapa jawaban untuk beberapa pertanyaan.
Saya melihat tiga opsi utama untuk 'berbagi' data antar ruang. Meskipun sebagian besar posting adalah tentang berbagi data antar sistem, saya merasa hal yang sama dapat diterapkan untuk berbagi data antar sistem.
1. Permintaan
Contoh : Jika dunia HUD perlu mengetahui kesehatan pemain saat ini, ia dapat menanyakan dunia lain dan menanyakan kesehatan saat ini.
Kelemahan : Dunia perlu tahu tentang satu sama lain yang merupakan masalah ketergantungan utama dan bertentangan dengan decoupling.
2: Pesan langsung (sinkronisasi dan asinkron)
Contoh : Jika selama pertempuran kesehatan seorang pemain berubah, ia dapat mengirim pesan (sinkronisasi dan asinkron, apa pun yang diperlukan) ke dunia lain yang perlu tahu tentang perubahan ini.
Kelemahan : Masih masalah decoupling: dunia perlu tahu tentang satu sama lain.
3: Perpesanan tidak langsung (sinkronisasi dan asinkron) <- opsi terbaik
Contoh : Jika selama pertempuran kesehatan seorang pemain berubah, ia dapat mengirim pesan (sinkronisasi dan asinkron, apa pun yang diperlukan) ke hub pesan umum. Dunia / sistem lain yang perlu tahu tentang perubahan ini berlangganan saluran pesan tertentu dan membaca pesan.
Terbalik : Dipisahkan sepenuhnya, mudah dikelola dan diperpanjang.
Kekurangan / tidak jelas : Kapan saluran pesan mengetahui bahwa pesan-pesan perlu dihapus? Atau mungkin sistem yang berlangganan tanda (hanya untuk dirinya sendiri) pesan sebagai sudah dibaca dan menunggu pesan baru -> messagebox menjadi sangat besar setelah beberapa saat. Bagaimana dunia / sistem menangani ketertiban? Misalnya selama bingkai: jika HUD sudah melakukan polling pesan kesehatan dan setelah itu kesehatan berubah, frame berikutnya HUD akan diperbarui. Untuk beberapa aplikasi ini mungkin bukan cara yang benar.
T: Objek game tunggal dapat ada di beberapa ruang
Saya menggunakan kerangka kerja Artemis ECS yang dilengkapi dengan ruang built-in (disebut dunia). Setiap entitas (dan dengannya, data dalam bentuk komponen) dibuat di dunia dan karenanya tidak dapat dibagi di antara dunia.
Jawaban:
Salah satu cara untuk melihatnya adalah Anda mungkin memasukkan terlalu banyak ke dalam objek game Anda.
Tidak ada alasan bahwa kode yang benar-benar menghubungkan HUD ke gim di dunia Anda harus berada dalam komponen / sistem yang hidup di ruang tertentu. Kode itu mungkin akan lebih baik tinggal di manajer pusat atau skrip global yang memiliki akses ke semua ruang dan semua objek, dan kemudian dapat berinteraksi dengan kode yang tahu kapan harus benar-benar membuat ruang dan apa yang harus dimasukkan ke dalamnya (misalnya kode yang memunculkan pemain, menyimpan kondisinya di antara level, dll.).
Anda juga bisa memiliki "ruang master" yang menyimpan objek game dengan logika atau data yang perlu bertahan masa lalu atau memanipulasi ruang yang digunakan untuk level dan UI. Pendekatan itu umum di mesin yang memaksa pengembang untuk menempatkan semua skrip / logika ke komponen / objek (misalnya, di Unity, Anda akan membuat objek Utama global dan mengaturnya untuk bertahan di seluruh adegan pembongkaran; jika Unity benar-benar memiliki ruang, Anda ' d gunakan itu bukan bendera).
Ingat, menyalahgunakan ECS Anda sama dengan menyalahgunakan pola desain; hanya karena Anda memiliki beberapa alat baru yang bagus tidak berarti Anda harus menggunakannya untuk menyelesaikan setiap masalah yang Anda temui. Evaluasilah ruang masalah Anda dan pilih solusi yang paling pas, bahkan jika itu adalah hal suram yang digunakan leluhur Anda di zaman kegelapan 90-an. : p
sumber
Saya memang membuat beberapa prototipe tetapi tidak ada yang terlalu besar dan cara saya dulu menangani banyak ruang hanyalah membuat objek permainan yang berisi, dunia, pemain dll. Daripada saya membuat beberapa properti yang dibutuhkan oleh beberapa ruang lain misalnya kesehatan. , dalam objek game
Setiap kali dipanggil itu akan mendapatkan kesehatan pemain. dengan begitu saya bisa mengirimnya ke HUD dan menampilkan bar kesehatan.
Ini bukan yang terbersih tetapi menyelesaikan pekerjaan, saya melakukan beberapa pengujian kinerja pada tahun 2013 dan semuanya tampak berjalan lancar. untuk menghindari ketergantungan seperti itu Anda selalu dapat menjatuhkan bilah kesehatan saat kesehatan pemain nol.
Biasanya ketika pemain tidak ada itu berarti bahwa pengguna berada di menu atau cut-scene.
Contoh Kode:
Semoga ini yang kamu cari.
sumber
ini adalah sesuatu yang saya kerjakan dalam beberapa minggu terakhir. Saya sedang mengerjakan perpustakaan ECS saya sendiri (ingin melakukan itu untuk pengalaman dan hanya untuk mencobanya, karena saya ingin melakukannya selama beberapa waktu).
Ini adalah tautan github: https://github.com/gioragutt/xna-ecs
Untuk masalah Anda, saya selalu menulis perpustakaan pubsub kecil, yang dapat Anda lihat di sini
Pada dasarnya, saya memiliki
EmsClient
kelas, dari mana hal-hal itu berasal. Saat ini, komponen saya tidak melakukan itu, tetapi kelas tingkat yang lebih tinggi, meskipun tidak ada alasan untuk tidak melakukannya. Saya berlangganan Nama pesan, dan menyediakan callback dengan tanda tangan berikut:Action<JObject>
. Seperti yang sudah Anda pahami, saya menggunakan Json Objects sebagai sarana untuk mentransfer pesan. Saya sudah melakukan ini setelah saya sebelumnya hanya digunakanbyte[]
's, dan saya menemukan bahwa saya membutuhkan sesuatu yang lebih umum, dan karena saya terbiasa dengan hal seperti itu dari tempat kerja saya (kami memiliki IPCD yang bekerja sama, kecuali panggilan balik). Metode selalu sama, karena biasanya kami memisahkan tanggung jawab ke penangan yang berbeda).Ada
EmsServer
(satu di server, dan satu di setiap klien) yang bertanggung jawab untuk memindahkan pesan di antaraEmsClient
itu di ranah (EmsServer
di sisi server memindahkan pesan di antaraEmsClients
di sisi server, dan sebaliknya untuk sisi klien).Untuk pengiriman pesan antara Klien dan Server, saya membuat
EmsServerEndpoint
yang merupakanEmsClient
dirinya sendiri, dia hanya melakukan logika buffering pesan yang dikirim pada ranah itu, dan membilasnya ke ranah lain (FE klien mengirim pesan ke server, sedangkan ketika server mentransfer setiap pesan ke semua klien yang terhubung.Anda dapat melihat penggunaan di banyak tempat, fe:
ClientGameManager
,ServerGameManager
.Sedangkan, untuk contoh Anda, jika saya ingin menambahkan komponen GUI untuk pemain, Anda dapat melihat DI SINI , di
BeginAllocateLocal
danBeginAllocateRemote
metode, yang bertanggung jawab untuk membangunGameObjects
para pemain. MasingGameObject
- masing berisiEntity
(dari lib ECS) danIComponentContainer
(yang juga, dari lib ECS). Masing-masingGameObject
secara otomatis mendapat transformasi (seperti diUnity
, dari mana saya mengambil inspirasi).Kode saya cukup banyak berbicara untuk dirinya sendiri, dan jika Anda mendapatkannya, saya mencari kritik untuk itu, jadi saya ingin kritik yang membangun :)
Semoga kode saya akan membantu Anda dengan beberapa ide!
sumber
Pertimbangkan komponen pengamat / subjek untuk komponen gim Anda dan komponen ui. Anda menyambungkannya pada saat membuat / memuat dan kemudian melupakannya. Jika kesehatan karakter berubah, ia memberi tahu semua pengamat, yang dapat melakukan apa pun yang mereka inginkan dengan informasi tersebut.
sumber