Apa yang harus dikirim ke server dalam game FPS waktu nyata?
23
Apa cara yang tepat untuk memberi tahu posisi pemain lokal kami ke server? Beberapa dokumen mengatakan bahwa lebih baik mengirim input kapan pun diproduksi. Dan beberapa dokumen mengatakan klien mengirim posisinya dalam interval tetap.
Dengan mengirim pendekatan input: Apa yang harus saya lakukan jika pemain menekan tombol arah? Itu berarti saya harus mengirim paket ke server di setiap frame. Bukankah terlalu banyak? Dan ada juga rotasi pemain dari input mouse. Berikut ini sebuah contoh:
Jawaban sederhana: curang atau jangan seakurat itu!
Jika Anda memainkan beberapa penembak online, kemungkinan besar Anda akan mengalami apa yang disebut "karet banding" jika koneksi Anda ke server buruk.
Ini disebabkan oleh klien Anda memperbaiki posisi Anda dari waktu ke waktu.
Pada dasarnya, apa yang terjadi di kedua sisi:
Server akan melacak pergerakan Anda dan mengirim pembaruan ke klien seperti yang diharapkan. Ini tidak selalu harus menjadi pembaruan penuh. Setiap x frame bisa ada pembaruan penuh, semua frame lain Anda hanya mengirim vektor kecepatan baru (jika ada perubahan).
Klien Anda sendiri akan memungkinkan Anda untuk bergerak bebas tetapi akan menggunakan pembaruan yang disediakan oleh server untuk memperbaiki / menyesuaikan posisi Anda. Ini akan memastikan game terasa responsif, bahkan jika Anda tidak memperbarui posisi frame demi frame.
Tetapi bagaimana input ditangani? Klien Anda akan mengirim posisi Anda ke server "Saya pindah ke sana." Server akan memverifikasi pembaruan ini (misalnya apakah Anda dapat pindah ke sana secepat itu?) Dan jika itu valid, Anda (atau menolak pembaruan Anda, menghasilkan "karet gelang").
Jadi ya, pendekatan interval tetap Anda kemungkinan besar akan berhasil dan cukup.
Tetapi bahkan jika Anda ingin mengirim input dan menangani gerakan di kedua sisi, perlu diingat bahwa Anda tidak harus mengirim "tombol masih ditekan". Alih-alih, kirim satu acara saat tombol ditekan dan yang lainnya setelah tombol dilepaskan.
Ya saya bisa melacak pers dan melepaskan tombol. Tapi bagaimana dengan input mouse? Itu terus berubah.
syloc
6
"Alih-alih, kirim satu acara saat tombol ditekan dan yang lain setelah tombol dilepas." - Benar, tetapi perlu ada cek di tempat untuk memastikan bahwa acara "on release" akhirnya dipaksakan, tergantung pada aturan permainan. Misalnya, dalam multipemain Rainbow Six Vegas 2 , pemain dapat mulai menembakkan senjatanya, dan bug (sayangnya umum) menyebabkan pesan "hentikan tembakan" untuk tidak berhasil mencapai server. Ini menghasilkan audio tembakan yang tersisa di loop tak terbatas selama sisa pertandingan. Hanya satu contoh yang harus diwaspadai. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: Pegang saja sisi klien dan biarkan server menentukan apakah gerakan itu valid / mungkin (untuk mencegah hal-hal seperti peretasan teleport dan sejenisnya).
Mario
@syloc Cukup tetapkan interval untuk mouse, tetapi untuk menghemat bandwidth tambahan masih melakukan pemeriksaan sisi klien untuk melihat apakah itu diubah. Jika ada periode waktu tanpa gerakan mouse, Anda tidak perlu terus mengirim pesan tentang hal itu.
agweber
Di salah satu pekerjaan saya, kami memiliki seorang insinyur yang praktis mendorong dirinya sendiri gila mengoptimalkan perilaku pegas untuk pembaruan posisi yang terlewat untuk dial-up (13 tahun yang lalu). Sekarang saya melihat game dengan banyak bandwidth dan latensi sangat rendah yang menderita masalah ini, sepertinya masalah ini tidak akan pernah hilang atau bahwa orang-orang kurang peduli tentang hal itu akhir-akhir ini.
Ini menjelaskan mengapa disarankan untuk menggunakan pengiriman paket 'interval tetap'. Singkatnya, itu sebenarnya terutama penting untuk paket yang dikirim oleh server.
Mengirim paket memiliki biaya tetap, dan ukuran maksimum paket jaringan sekitar 1,5 KB. Jadi jika Anda memiliki misalnya 16 pemain di server Anda, setiap frame ketika Anda menghitung pergerakan pemain, kode naif dapat mengirim paket pembaruan ke setiap pemain setelah setiap resolusi gerakan, jadi 16 * 16 = 256 paket. Jika Anda memiliki framerate 30, itu adalah 7680 paket.
Pendekatan yang lebih baik, adalah membuat buffer di setiap awal frame, menggabungkan di dalamnya 16 posisi Anda yang diperbarui, dan kemudian mengirimkannya ke 16 pemain Anda.
Anda sekarang hanya mengirim 480 paket per detik untuk hasil yang sama.
Dalam kasus pemain-ke-server, itu berarti Anda harus mengirim, dalam paket yang sama, maksimum data, seperti; posisi tampak, tindakan yang disebut bingkai ini dan sebagainya.
Tentang bagian kedua dari pertanyaan Anda - cara saya memilih untuk mengurangi sensasi jeda adalah dengan mengirim informasi ini ke server pada setiap frame:
posisi aktual pemain saat ini (digunakan oleh server untuk memeriksa apakah sisi server dan posisi sisi pemain tidak terlalu tersinkronisasi).
Perkiraan posisi pemain dalam 1 detik: dihitung oleh klien: jika pemain tidak mengubah arah mouse dan meninggalkan keyboard dalam kondisi saat ini selama 1 detik, di mana akan menjadi pemain? (kami tidak peduli tentang tabrakan) Jika pemain tidak bergerak, maka posisinya yang diperkirakan dalam 1 detik adalah posisi saat ini.
Posisi yang dia lihat.
Setiap kali server menerima informasi ini, ia memperbarui posisi masa depan dan melihat posisi, dan entitas pemain akhirnya bergerak menuju posisi masa depannya.
Pemain tidak pernah benar-benar disinkronkan, tetapi input input instan (paling penting bagi saya) dan saya menemukan posisi prediksi cukup akurat untuk saya.
"Pemain tidak pernah tidak pernah benar-benar disinkronkan" Saya pikir ini juga penting untuk menyebutkan bahwa tingkat akurasi di sini tergantung pada permainan yang sebenarnya (bermain). Sebagai contoh, MMO klasik di mana Anda cukup mengklik dan memilih entitas, tidak akan membutuhkan akurasi sempurna untuk hampir semua, tetapi dalam penembak, sinkronisasi yang baik dan sempurna sangat penting.
Mario
Masalahnya, tidak ada orang waras yang menggunakan TCP untuk FPS. Mereka lebih suka berurusan dengan pengurutan ulang yang rumit dan melewatkan datagram daripada mengeluarkan TCP.
Jika Anda belum melakukannya, saya sarankan Anda untuk membaca dua artikel yang mendalam tetapi dapat dimengerti ini: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking dan http://fabiensanglard.net/quake3/network.php .
Ini menjelaskan mengapa disarankan untuk menggunakan pengiriman paket 'interval tetap'. Singkatnya, itu sebenarnya terutama penting untuk paket yang dikirim oleh server.
Mengirim paket memiliki biaya tetap, dan ukuran maksimum paket jaringan sekitar 1,5 KB. Jadi jika Anda memiliki misalnya 16 pemain di server Anda, setiap frame ketika Anda menghitung pergerakan pemain, kode naif dapat mengirim paket pembaruan ke setiap pemain setelah setiap resolusi gerakan, jadi 16 * 16 = 256 paket. Jika Anda memiliki framerate 30, itu adalah 7680 paket.
Pendekatan yang lebih baik, adalah membuat buffer di setiap awal frame, menggabungkan di dalamnya 16 posisi Anda yang diperbarui, dan kemudian mengirimkannya ke 16 pemain Anda.
Anda sekarang hanya mengirim 480 paket per detik untuk hasil yang sama.
Dalam kasus pemain-ke-server, itu berarti Anda harus mengirim, dalam paket yang sama, maksimum data, seperti; posisi tampak, tindakan yang disebut bingkai ini dan sebagainya.
Tentang bagian kedua dari pertanyaan Anda - cara saya memilih untuk mengurangi sensasi jeda adalah dengan mengirim informasi ini ke server pada setiap frame:
posisi aktual pemain saat ini (digunakan oleh server untuk memeriksa apakah sisi server dan posisi sisi pemain tidak terlalu tersinkronisasi).
Perkiraan posisi pemain dalam 1 detik: dihitung oleh klien: jika pemain tidak mengubah arah mouse dan meninggalkan keyboard dalam kondisi saat ini selama 1 detik, di mana akan menjadi pemain? (kami tidak peduli tentang tabrakan) Jika pemain tidak bergerak, maka posisinya yang diperkirakan dalam 1 detik adalah posisi saat ini.
Posisi yang dia lihat.
Setiap kali server menerima informasi ini, ia memperbarui posisi masa depan dan melihat posisi, dan entitas pemain akhirnya bergerak menuju posisi masa depannya.
Pemain tidak pernah benar-benar disinkronkan, tetapi input input instan (paling penting bagi saya) dan saya menemukan posisi prediksi cukup akurat untuk saya.
sumber