Sistem komponen entitas - perkembangan game

8

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 componentskebutuhan 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.

Tim
sumber
Perpesanan adalah pendekatan standar di sini: gamedev.stackexchange.com/questions/23834/…
MichaelHouse
Dari apa yang dapat saya baca di artikel yang ditautkan objek permainan tunggal dapat ada di bawah beberapa spasi. Jika Anda memiliki grafik atau logika yang berbeda antara spasi, pisahkan data dari grafik dan logika. Bagikan objek data game di seluruh ruang dan gabungkan dengan objek grafis dan logika game yang berbeda.
Andreas
Jawaban yang saya berikan tentang sistem pengiriman pesan ini dapat membantu Anda juga: gamedev.stackexchange.com/questions/7718/…
James
Saya telah menerapkan ketiga solusi (kueri, langsung dan tidak langsung) dalam kehidupan gamedev saya. Dan saya dapat mengatakan bahwa opsi ketiga paling cocok untuk saya. Anda dapat dengan mudah memisahkan sistem dan menjalankan logika mereka secara paralel. Satu-satunya downside adalah bahwa Anda harus melakukan 9 panggilan fungsi untuk merutekan setiap pesan / acara dari satu sistem ke sistem lainnya. Jelas Anda dapat mengoptimalkannya dan plus besar adalah Anda tidak perlu mutex atau lajang dalam pendekatan ini.
Gregory
@Gregory Terima kasih atas imput Anda, saya berharap pesan tidak langsung menjadi pilihan terbaik. Saya tidak mengetahui 9 fungsi panggilan tetapi ketika merencanakan pesan ini saya menyadari bahwa memang itu akan menjadi sedikit panggilan. Apakah Anda pernah menemukan solusi / alternatif yang baik untuk penghapusan pesan ketika tidak ada sistem yang membutuhkannya lagi?
Tim

Jawaban:

1

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

Sean Middleditch
sumber
0

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:

public float PlayerHealth {
  get {
    if (player !+ null) 
      return player.Health;
    return -1;
  }
}

Semoga ini yang kamu cari.

Clayton C
sumber
0

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 EmsClientkelas, 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 antara EmsClientitu di ranah ( EmsServerdi sisi server memindahkan pesan di antara EmsClientsdi sisi server, dan sebaliknya untuk sisi klien).

Untuk pengiriman pesan antara Klien dan Server, saya membuat EmsServerEndpointyang merupakan EmsClientdirinya 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 BeginAllocateLocaldan BeginAllocateRemotemetode, yang bertanggung jawab untuk membangun GameObjectspara pemain. Masing GameObject- masing berisi Entity(dari lib ECS) dan IComponentContainer(yang juga, dari lib ECS). Masing-masing GameObjectsecara 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!

Giora Guttsait
sumber
0

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.

Ian Young
sumber