Multiplayer platformer - Apakah koreksi server biasanya diperlukan dengan satu klien di server?


10

Saat ini saya sedang mengerjakan platformer multiplayer yang agak sederhana. Saya membaca cukup banyak artikel tentang teknik yang digunakan untuk menyembunyikan latensi, tetapi saya masih gagal memahami beberapa konsep. Saya menemukan topik yang sangat menarik dan suka mencoba ide sendiri, tetapi saya pikir meminta gamedev stackexchange akan lebih efisien untuk pertanyaan saya. Saya akan mencoba yang terbaik untuk menggambarkan situasi saya saat ini dan pertanyaan apa yang muncul di sepanjang jalan.

Saat ini, saya hanya ingin satu pemain disinkronkan dengan server. Secara teoritis, saya mengasumsikan seorang pemain sendiri dengan prediksi sisi klien tidak akan memerlukan koreksi server, karena tidak ada faktor eksternal yang mempengaruhi pergerakannya. Oleh karena itu, prototipe saya saat ini hanya memiliki satu pemain yang disinkronkan dengan server tanpa koreksi server yang dikirim.

Jika Anda terbiasa dengan jaringan game, saya pikir Anda dapat melewati bagian konteks, meskipun saya mungkin telah melakukan sesuatu yang salah di sepanjang jalan.

Lingkaran klien (sekali per bingkai, sekali setiap ~ 16,67 ms)

Simpul klien yang disederhanakan terlihat seperti:

  1. Periksa input lokal (WASD) dan kemaslah sebagai tindakan (mis Type=MoveLeft, Time=132.0902, ID=15.). Kami menjaga tindakan paket untuk akhirnya mengirimnya nanti. Selain itu, kami langsung menerapkan tindakan yang diinginkan ke simulasi fisika lokal gim. Sebagai contoh, jika kita memiliki MoveLeftaksi, kita menerapkan gaya ke kiri pada kecepatan pemain.

  2. Periksa untuk mengirim tindakan. Untuk mencegah penyalahgunaan bandwidth klien, hanya mengirim tindakan paket pada interval tertentu (misalnya 30 ms).

  3. Terapkan modifikasi server. Pada titik tertentu ini akan menangani delta dan koreksi yang diterima oleh server dan menerapkannya pada simulasi permainan lokal. Untuk pertanyaan khusus ini, ini tidak digunakan.

  4. Perbarui fisika setempat. Jalankan loop fisika pada pemain utama. Pada dasarnya, ini melakukan prediksi sisi klien dari pergerakan pemain. Ini menambah gravitasi pada kecepatan pemain, menerapkan kecepatan pemain ke posisinya, memperbaiki tabrakan di sepanjang jalan, dll. Saya harus menentukan bahwa simulasi fisika selalu dijalankan dengan delta tetap (disebut beberapa kali tergantung pada detik delta nyata) .

Saya melewatkan beberapa detail spesifik tentang fisika dan bagian lain karena saya merasa mereka tidak diharuskan untuk pertanyaan, tetapi merasa bebas untuk memberi tahu saya jika mereka akan relevan dengan pertanyaan itu.

Server loop (setiap 15 ms)

Loop server yang disederhanakan terlihat seperti:

  1. Tangani tindakan. Periksa paket tindakan yang diterima dari klien dan terapkan pada simulasi fisika server. Sebagai contoh, kita dapat menerima 5 MoveLeftaksi, dan kita akan menerapkan gaya pada kecepatan 5 kali . Penting untuk dicatat, paket seluruh tindakan dijalankan pada satu "bingkai" , berlawanan dengan klien di mana ia diterapkan segera setelah tindakan terjadi.

  2. Perbarui logika game. Kami memperbarui fisika permainan, menggerakkan pemain, dan memperbaiki tabrakan, dll. Kami juga mengemas setiap peristiwa penting yang kebetulan dikirim ke pemain (mis. Kesehatan pemain turun, pemain meninggal, dll.) Nanti.

  3. Kirim koreksi. Kami secara teratur (mis. Setiap 35 ms) mengirim delta ke pemain lain (mis. Posisi pemain, kesehatan, dll.) Jika baru saja diubah. Bagian ini saat ini tidak diimplementasikan, karena saya ingin simulasi pemain tunggal untuk memberikan hasil yang sama pada klien dan server tanpa koreksi, untuk memastikan bahwa prediksi sisi klien berfungsi dengan baik.

Masalah

Sistem saat ini berfungsi dengan baik dalam keadaan sederhana, dan saya senang terkejut melihat bahwa ia memberikan hasil yang sangat mirip dengan gerakan horisontal sederhana (ketidakakuratan disebabkan oleh kesalahan presisi titik mengambang, saya percaya):

Sinkronisasi berfungsi dengan baik dengan tabrakan / gerakan sederhana

Abaikan grafik prototipe. Kotak putih = pemain, Kotak merah = rintangan, Biru = latar belakang

Namun, saya mendapatkan kesalahan sinkronisasi setelah melakukan gerakan sensitif waktu, seperti melompat dan bergerak mendekati rintangan yang terisolasi:

Sinkronisasi tidak berfungsi karena saya melompati rintangan yang ditentukan pada saat-saat sensitif waktu

Secara teori, saya berharap keduanya selalu berakhir dengan hasil yang sama, karena tidak ada faktor eksternal pada klien yang mempengaruhi posisinya. Namun dalam praktiknya, saya pikir saya mengerti masalahnya.

Karena melompati rintangan seperti itu sangat tergantung pada waktu pemain, variasi kecil ketika kecepatan diterapkan pada posisi akan berakibat pada hasil (misalnya klien bisa bergerak tepat pada waktunya untuk menghindari tabrakan dengan pemain). Kendala, sementara server akan melakukannya karena menerima paket tindakan keseluruhan di kemudian hari dan tetap terjebak pada kendala untuk sejumlah kecil waktu, mengubah hasil akhir). Perbedaan antara bagaimana klien dan server menanganinya adalah bahwa klien melakukan semua tindakannya saat terjadi, sementara server melakukan semuanya dalam bulks saat menerimanya.

Pertanyaan

Konteks panjang ini akhirnya mengarah ke pertanyaan saya (terima kasih telah membaca sejauh ini): Apakah normal untuk meminta koreksi server walaupun hanya ada satu pemain yang disinkronkan dengan server, atau haruskah saya menggunakan teknik tertentu untuk menghindari desinkronisasi pada situasi yang peka waktu ?

Saya telah memikirkan solusi tertentu yang mungkin, beberapa di antaranya saya kurang nyaman dengan:

  1. Terapkan koreksi server. Anggap saja ini perilaku normal dan perbaiki kesalahan yang terjadi. Saya ingin mengimplementasikannya, tetapi saya hanya ingin memastikan bahwa apa yang telah saya lakukan sejauh ini dapat diterima.

  2. Gunakan waktu klien yang disediakan untuk menerapkan tindakan yang diinginkan. Saya kira ini akan mirip dengan kompensasi lag, yang membutuhkan "kembali ke masa lalu" dan memeriksa pergerakan. Seperti menerapkan koreksi server, kembali ke masa lalu dan mengajukan kembali tindakan selanjutnya setelah itu. Saya sangat tidak menyukai ide itu. Itu terlihat rumit, mahal dalam sumber daya dan membutuhkan kepercayaan waktu yang diberikan klien (walaupun saya berencana untuk benar-benar memeriksa bahwa waktu terlihat relatif sah).

  3. Tanyakan GameDevelopment StackExchange untuk ide baru yang hebat yang akan memperbaiki semua masalah saya.

Saya baru memulai di dunia jaringan game, jadi silakan koreksi / kritik / penghinaan salah satu konsep di atas atau berikan ide / sumber daya yang dapat membantu saya sepanjang perjalanan saya di Dunia Jaringan yang Luar Biasa. Maafkan saya jika saya dapat menemukan jawaban saya di tempat lain, saya gagal dalam hal itu.

Terima kasih banyak atas waktu berharga Anda.


Server dan klien Anda menjalankan bingkai dengan kecepatan berbeda. Apa yang terjadi jika klien melakukan dua tindakan pada frame yang berurutan, tetapi server melihat celah satu-frame di antara mereka?
user253751

@immibis mendasarkan diri saya pada gafferongames.com/game-physics/fix-your-timestep untuk meminimalkan efek ini.
Jesse Emond

Jawaban:


11

Dalam kasus seperti itu, Anda mungkin lebih baik membiarkan klien sedikit berwibawa. Untuk kontrol yang presisi seperti itu, Anda sangat tidak mungkin mendapatkan perilaku yang baik bahkan dengan koreksi dan prediksi yang sangat canggih.

Klien perlu memperluas dari hanya mengirim pesan "Saya melompat" ke mengirim "Saya melompat dari X, Y pada waktu T" pesan. Server kemudian memeriksa bahwa lokasi itu berada dekat dengan apa yang ia pikir pemain pada waktu T (yang dapat Anda batasi untuk waktu yang cukup kecil di masa lalu) untuk melindungi dari kecurangan, kemudian mensimulasikan lompatan dari posisi klien dikirim. Server hanya mengoreksi klien ketika jauh dari pukulan (biasanya karena lag atau sejenisnya).

Teknik semacam ini digunakan bersama dengan koreksi dan interpolasi untuk membuat permainan terasa responsif pada klien lokal dan terlihat mulus untuk klien jarak jauh.


Sangat menarik. Saya akan mencoba menerapkan ini dan melihat bagaimana kelanjutannya. Terima kasih banyak telah meluangkan waktu untuk menjawab. Ngomong-ngomong, Anda menyebutkan "dalam jarak dekat" dan "waktu yang cukup kecil di masa lalu", akankah Anda cukup memeriksa masing-masing dengan jarak dan waktu yang konstan? Atau Anda akan menggunakan teknik yang lebih canggih seperti menyimpan riwayat posisi dan menggunakan Waktu Perjalanan Pulang Pergi rata-rata klien (atau yang lainnya, benarkah)?
Jesse Emond

Apa pun yang berfungsi untuk gim Anda. Mulai dari yang sederhana, rumit hanya sampai tingkat yang Anda anggap perlu. Beberapa server memang menyimpan riwayat snapshot untuk ~max(RTT)kutu server di masa lalu, tetapi apakah Anda perlu untuk game Anda secara khusus saya tidak tahu. Ini bisa menjadi lebih berguna untuk gim bergaya penembak di mana Anda juga ingin melakukan beberapa level deteksi hit / shot pada klien dan tidak hanya perlu tahu di mana seorang pemain 46ms lalu, tetapi juga di mana targetnya 46ms lalu dan di mana ada memindahkan platform oklusi di mana.
Sean Middleditch

Sempurna. Saya akan bereksperimen dan melihat mana yang paling berhasil. Menandainya sebagai jawaban yang diterima, terima kasih lagi!
Jesse Emond
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.