Bagaimana cara menyinkronkan status permainan multi-pemain lebih efisien daripada pembaruan kondisi-penuh?

10

Saya telah melakukan sedikit pengkodean jaringan gim sebelumnya, tetapi utamanya dengan TCP untuk gim tanpa kebutuhan waktu nyata. Saya sedang mengerjakan game Java 2D dengan multiplayer berjaringan. Untuk belajar, saya ingin melakukan ini sendiri, tanpa API jaringan yang ada.

Bagaimana cara saya secara efisien mewakili kondisi permainan yang dikirim ke klien dari server? Ada cara yang paling jelas tetapi mungkin paling tidak efisien, yaitu membuat semacam objek konteks keadaan permainan dengan lokasi masing-masing pemain, keadaan animasi, dll., Dan mengirimkannya ke setiap pemain setiap pembaruan . Itu tampaknya tidak terlalu sulit untuk diterapkan, tetapi mungkin akan terlalu besar untuk mencapai sesuatu yang mendekati interaksi waktu nyata (tentu saja pengalaman saya dengan ini terbatas sehingga saya mungkin salah).

Apakah ada cara yang solid yang pernah Anda gunakan sebelumnya untuk hanya mengirimkan perubahan dalam kondisi, dan apakah bahkan ada perbedaan kinerja yang cukup besar sehingga layak untuk pekerjaan ekstra?

Haz
sumber
2
Cobalah keadaan penuh setiap frame dan jika terlalu lambat (untuk game 2d yang agak sederhana, mungkin cukup efisien) kemudian coba optimalkan. Jika berfungsi dengan baik, maka berfungsi dengan baik dan Anda tidak perlu mengubahnya kecuali jika Anda melihat jaringan Anda menjadi hambatan nanti.
Robert Rouhani

Jawaban:

10

Mentransmisikan kondisi permainan penuh secara teratur biasanya tidak layak, meskipun hal itu sangat tergantung pada kompleksitas permainan Anda. Untuk gim sederhana dengan model dunia kecil, gim ini bisa bekerja.

Saya pribadi lebih sukses dengan model berikut:

  • Keadaan gim disimpan dalam model objek yang terdefinisi dengan baik dalam struktur data spasial (misalnya, sebuah octree)
  • Semua perubahan pada status permainan (baik pada klien atau server) dijelaskan sebagai peristiwa. Suatu peristiwa bisa berupa perubahan properti pada objek game, perubahan ubin peta, pergerakan objek game, dll.
  • Mesin gim di server menghasilkan aliran acara saat gim berlangsung. Ini langsung diterapkan ke keadaan permainan server.
  • Acara juga dikirim ke pemain, tetapi hanya jika acara tersebut relevan dengan pemain itu (mis. Apakah acara tersebut terlihat dari posisi saat ini?)
  • Perubahan visibilitas pemain juga dapat menyebabkan acara untuk "mengungkapkan" bagian-bagian baru peta dll ketika pemain bergerak. Ini juga dapat digunakan untuk memastikan bahwa pemain mendapatkan tampilan awal yang akurat dari kondisi permainan yang relevan saat mereka pertama kali bergabung dalam permainan.
  • Status permainan untuk pemain diperbarui dengan acara apa pun yang diterimanya. Karena itu hanya memiliki sebagian model dari kondisi permainan, tetapi harus tetap sinkron dengan server dengan asumsi semua acara diproses dengan benar

Ini telah memberikan kinerja yang baik bagi saya dengan dunia game yang bahkan cukup besar.

Kiat lain, biarkan klien mengurus animasi, efek partikel dll. Tanpa referensi ke server. Tidak ada gunanya mengirimkan ini - mereka hanya perlu "dipicu" oleh peristiwa permainan yang sesuai.

mikera
sumber
6

Sinkronisasi biasanya dibagi menjadi dua bagian: inkremental dan absolut.

Kadang-kadang Anda harus mengirimkan semuanya, itu besar, tetapi jika Anda mengemasnya dengan cara yang benar Anda bisa melakukan ini setiap beberapa detik sekali. Adalah baik untuk menempatkan everithing di tempat, memperbaiki kesalahan penyegaran tambahan.

Untuk mencapai pengalaman real-time, Anda harus mengirimkan beberapa perubahan dengan cepat, tetapi hanya atribut yang dapat berubah. Misalnya, jika roket terbang dalam garis lurus, Anda tidak perlu memperbarui posisi, setiap klien dapat menghitungnya dari titik awal. Tetapi ketika itu mengenai, Anda dapat menghasilkan pesan tentang hal itu, sehingga setiap klien dapat meledak roket di tempat yang tepat. Gangguan kecil dapat diabaikan.

Tentu saja Anda hanya memperbarui barang, ketika mereka dapat mempengaruhi klien! Sesuatu yang jauh dari layar tidak sepadan. Beberapa nilai dapat diperbarui lebih jarang. Misalnya posisi penting untuk menjadi lebih atau kurang tepat, peristiwa (kematian, tembakan ditembakkan, ledakan, dll) harus dikirim secara instan, sementara tidak langsung nilai-nilai penting dapat memiliki periode refresh yang lebih rendah, misalnya papan skor, obrolan.

Pengemasan data juga penting. Anda dapat mengirim sekitar 1400 byte (tergantung konfigurasi, ini adalah default) dalam satu paket UDP, biasanya ada beberapa byte header. Sehingga Anda dapat memperbarui 50-100 posisi unit dalam satu paket dengan mudah.

Matzi
sumber
Terima kasih atas sarannya Matzi. Saya masih berupaya mengimplementasikan server dan klien, tetapi saya akan memeriksa kembali dalam beberapa hari dan mungkin menerima jawaban Anda.
Haz
Semoga beruntung untukmu! ;)
Matzi
1

Bergantung pada gim Anda, Anda mungkin mempertimbangkan model "eksekusi tersinkronisasi" di mana setiap klien memainkan gim yang sama hanya dengan berbagi input non-deterministik seperti input keyboard / joystick dan acara pengatur waktu. (Dibandingkan dengan model di mana setiap klien menjalankan simulasi lokal dan berharap untuk mengintegrasikan hasil dari simulasi jarak jauh). Mesin gim Anda umumnya harus sepenuhnya deterministik agar bisa berfungsi, yang dapat menjadi beban berat bergantung pada gim. Tetapi jika gim ini sudah deterministik, ini mungkin pendekatan yang lebih mudah.

Posting #AltDevBlogADay ini mencakup beberapa aspek dari pendekatan ini dalam RTS modern (khususnya cara mendeteksi kapan klien Anda mulai menjalankan game "berbeda".)

Ingatlah untuk tetap sederhana sampai terbukti sebaliknya. :)

PT
sumber
1
Ini adalah bacaan yang bagus dari pengembang Factorio yang menggunakan pendekatan ini, dan mengisyaratkan kompleksitas pendekatan ini, tetapi juga menunjukkan bahwa itu layak: factorio.com/blog/post/fff-76 factorio.com/blog/post/fff -147 factorio.com/blog/post/fff-188
AaronLS