Bagaimana cara kerja prediksi sisi klien?

33

Saya telah membaca Valve + Gafferon dan ratusan halaman dari Google, tetapi untuk alasan apa pun saya tidak bisa memahami prediksi klien.

Menurut pemahaman saya, masalah dasarnya adalah:

  • Klien A mengirimkan input di T0
  • Server menerima input di T1
  • Semua klien menerima perubahan di T2

Pada T2Namun, menggunakan prediksi klien, klien A adalah sekarang di posisi yang tepat untuk T4.

Bagaimana Anda memastikan bahwa Klien A, ketika memprediksi bahwa server akan menerima permintaan perpindahan, tidak akan berada di depan server? Jelas sepanjang waktu mereka di depan, ini menghasilkan gertakan kembali ke tempat server terakhir melihat mereka. Dengan semua koreksi yang telah saya coba, ini masih terlihat ketika Anda berhenti, karena server berhenti di belakang Anda

Chris Evans
sumber

Jawaban:

35

Saya menulis serangkaian artikel tentang ini. Ini didasarkan pada ide-ide yang sama yang Anda baca di tempat lain, tetapi dijelaskan dengan cara yang sangat rinci dan (saya harap) dapat diakses.

Secara khusus, artikel tentang prediksi sisi klien adalah yang ini .

ggambett
sumber
Artikel bagus :-) Saya ingin melihat bagian keempat dari seri ini. Sebagai saran kecil, tautan ke bagian selanjutnya di akhir setiap artikel pasti akan meningkatkan navigasi.
ATAU Mapper
5
@ORMapper - Saya akhirnya menulis artikel ke-4! gabrielgambetta.com/fpm4.html
ggambett
Kudos untuk seri artikel Anda :-) Sangat membantu, terima kasih :-)
ATAU Mapper
Semua artikel (saya bisa temukan) yang berbicara tentang merekonstruksi masa lalu menggunakan snapshot yang disimpan mengambil contoh pengambilan gambar. Apakah ini berlaku untuk pergerakan juga? Saya bisa membayangkan bahwa resimulasi gerakan dapat menyebabkan beberapa perbedaan besar bagi pemain lain jika mereka dapat saling bertabrakan. Katakanlah dua pemain bergerak melawan satu sama lain dan salah satunya berhenti bergerak beberapa "langkah" dari akan menjadi titik tabrakan. Perintah penghentian ini tiba terlambat karena kelambatan sehingga jika kita meniru dunia, kedua pemain akan berada di posisi yang sangat berbeda
Lope
Itu pertanyaan yang menarik. Sayangnya, saya tidak punya jawaban yang pasti. Saya kira itu tergantung pada seberapa kritis gerakan untuk permainan; apakah Anda hanya bertemu dengan orang lain dan tidak ada yang terjadi? Dalam hal server mungkin tidak peduli, itu dilihat sebagai kesalahan prediksi (kita semua pernah melihatnya terjadi dalam choke points, kan?). Apakah Anda membunuh pemain lain pada kontak? Dalam hal ini, memperbaikinya jauh lebih penting dan mungkin perlu ditata ulang. Perhatikan bahwa pada titik tertentu Anda perlu membuang beberapa paket sebagai "terlalu lama", jika tidak, Anda akan berpotensi menstimulasi ulang dari t = 0 setiap saat.
ggambett
4

Saya belum benar-benar menerapkan ini (jadi mungkin ada beberapa masalah yang tidak segera saya lihat), tetapi saya pikir saya akan mencoba membantu.

Inilah yang Anda katakan sedang terjadi:

Klien A mengirimkan input pada T0

Server menerima input di T1

Semua klien menerima perubahan di T2

Namun pada T2, menggunakan prediksi klien, Klien A sekarang pada posisi yang sesuai dengan T4.

Mungkin akan berguna untuk berpikir dalam hal waktu server. (Mungkin) sangat mirip dengan cara interpolasi bekerja.

Setiap perintah dikirim dengan waktu server. Waktu server ini diketahui pada awal pertandingan dengan menanyakan tanda centang server, mengkompensasi waktu ping. Pada klien Anda memiliki jumlah tick lokal Anda sendiri, dan setiap perintah yang Anda kirim dikonversi ke tick server (ini adalah operasi pengurangan sederhana)

Selain itu, klien selalu merender "di masa lalu". Jadi Anda berasumsi bahwa dunia yang dilihat klien adalah, katakanlah, 100 ms di belakang waktu server sebenarnya.

Jadi mari kita ulangi contoh Anda dengan waktu server (ditunjuk oleh S).

Klien mengirimkan input pada T0 dengan waktu server S0 (yang saya duga sebenarnya adalah "representasi klien dari waktu server dikurangi waktu interpolasi"). Klien tidak menunggu respons dari server dan segera bergerak.

Server menerima input di T1. Server menggambarkan posisi otoritatif klien pada waktu server S0 yang diberikan oleh klien. Mengirimnya ke klien.

Klien menerima posisi otoritatif di T2 (masih dengan penunjukan waktu server S0). Klien melacak sejumlah waktu lalu senilai peristiwa sebelumnya (mungkin hanya antrian dari semua prediksi yang belum dikonfirmasi).

Jika posisi / kecepatan / prediksi apa pun yang dikirim server pada S0 berbeda dari apa yang klien simpan di S0, klien menangani ini entah bagaimana. Baik dengan menjentikkan pemain kembali ke posisi masa lalu mereka, atau menstimulasi kembali input sebelumnya, atau mungkin sesuatu yang belum saya pikirkan.

Tetrad
sumber
3
Itu semua benar kecuali sedikit tentang rendering klien di masa lalu. Relatif ke server, klien sebenarnya merender di masa depan! Server tahu bahwa informasi yang dimilikinya dari setiap klien sudah lama dan bahwa setiap klien sudah berubah sejak saat itu.
Kylotan
2

Sebenarnya ada implementasi open-source di github yang menunjukkan bagaimana ini dilakukan. Lihat Lance.gg

github repo: https://github.com/lance-gg/lance

Kode prediksi klien diimplementasikan dalam modul yang disebut src/syncStrategies/ExtrapolateStrategy.js

Selain ekstrapolasi, ada dua konsep yang saya tidak lihat disebutkan di atas:

  1. Membungkuk tambahan. Pada dasarnya alih-alih menerapkan koreksi server sekaligus, Anda membiarkan delta berlaku sedikit demi sedikit. Dengan cara itu objek jarak jauh secara bertahap akan menyesuaikan posisi mereka agar sesuai dengan posisi server. Ada pembengkokan posisi, pembengkokan kecepatan, pembengkokan sudut, dan pembengkokan kecepatan sudut. Anda juga mungkin ingin faktor lentur berbeda untuk objek yang berbeda.
  2. Langkah Re-Enactment. Fakta bahwa data di masa lalu berarti Anda dapat mengembalikan waktu ke waktu data server, dan memulai kembali dari titik itu. Tentu saja Anda masih perlu membungkuk ke arah posisi yang baru ditemukan, daripada melompat ke sana.
Gary Weiss
sumber
1

Klien A selalu di depan server - tetapi tidak masalah. Anda hanya perlu mengembalikan klien jika server mengatakan ada masalah dengan posisi yang dilaporkan, di mana klien menjalankan kembali semua perubahan yang telah dibuat sejak kesalahan dengan nilai-nilai yang dikoreksi, untuk membawanya ke keadaan yang kompatibel. dengan server.

Untuk melakukan ini, klien perlu mengingat beberapa keadaan terakhir dan pembaruan masa lalu. Ini mungkin hanya beberapa nilai sederhana seperti posisi, kecepatan, orientasi, hal semacam itu. Server secara berkala akan mengirimkan pemberitahuan bahwa berbagai pembaruan klien adalah sah, artinya sekarang dapat dilupakan dari klien. Namun jika server melaporkan bahwa pembaruan tidak valid, keadaan klien memutar kembali ke titik itu dan perubahan di masa depan diterapkan ke keadaan yang dimodifikasi itu.

Ada beberapa tautan tambahan di bagian bawah artikel Valve yang layak dibaca - ini adalah salah satunya: https://developer.valvesoftware.com/wiki/Prediction

Kylotan
sumber
Jadi, apakah saya benar dalam berpikir bahwa klien (pada t=4) menerima info tentang t=2, sehingga mengatur ulang negara untuk t=2kemudian menjalankan kembali pembaruan untuk membawa objek dari t=2ke t=4?
George Duckett
Saya masih belum mengerti karena beberapa alasan. Server tidak diberi tahu posisi pemain, hanya inputnya. Jadi pemain tersebut bergerak dari posisi terakhir yang dikatakan oleh server. Masukan diterapkan. Server diinformasikan. Server mengkonfirmasi input ke semua orang. Dengan asumsi semua perintah diterima, server masih akan berada di belakang Klien A - jadi ketika Klien A berhenti, karakternya akan segera berhenti lalu geser kembali ke lokasi server ketika menerima konfirmasi berhenti.
Chris Evans
@ GeorgeDuckett: ya (walaupun tidak harus t = 4, bisa jadi setiap kali ada perbedaan, dan mungkin ada sejumlah pembaruan yang diterapkan kembali.)
Kylotan
@ChrisEvans: status + perubahan yang diketahui berdasarkan input sama dengan kondisi pengiriman. Adapun contoh pemberhentian, itu sendiri adalah input, dan server masih mensimulasikan gerakan sampai menerima input itu. Dengan asumsi latensi konstan, server akan menghentikan pemain yang bergerak pada posisi yang persis sama dengan yang dilihat klien ketika ia berhenti bergerak, karena klien berada di depan server. (Di dunia nyata, latensi bervariasi, jadi Anda menyisipkan sedikit untuk melicinkannya.)
Kylotan