Müşteri tarafı tahmini nasıl çalışır?


33

Valve + Gafferon ve Google’dan yüzlerce sayfa okudum, ama ne sebeple olursa olsun müşterinin öngörüsü üzerine gelemiyorum.

Anladığım kadarıyla temel sorun şudur:

  • A istemcisi adresinden giriş gönderir. T0
  • Sunucu girişi aldı T1
  • Tüm müşteriler bu değişikliği T2

Bununla T2birlikte, müşteri tahminini kullanarak, Müşteri A şimdi uygun bir konumdadır T4.

Sunucunun, hareket isteğini kabul edeceğini öngörürken A İstemcisinin sunucunun önünde olmayacağından nasıl emin olabilirsiniz? Açıkçası, önlerinde her zaman, bu, sunucunun en son gördüğü yere geri dönmesine neden olur. Denediğim tüm düzeltmelerde, durdurduğunuzda, sunucu arkanızda durduğundan dolayı, bu hala fark edilir

Yanıtlar:


35

Bununla ilgili bir dizi makale yazdım . Başka bir yerde okuduğunuz aynı fikirlere dayanıyor, ancak çok ayrıntılı ve (umarım) erişilebilir bir şekilde açıklanıyor.

Özel olarak, istemci tarafı tahmini ile ilgili makale bu .


Mükemmel makaleler :-) Serinin dördüncü bölümünü görmeyi çok isterim. Küçük bir öneri olarak, her bir makalenin sonundaki bir sonraki bölüme bağlantı kesinlikle gezinmeyi iyileştirecektir.
VEYA Eşleştiricisi

5
@ORMapper - Sonunda 4. makaleyi yazdım! gabrielgambetta.com/fpm4.html
ggambett

Makale diziniz için Kudos :-) Çok yardımcı oldu, teşekkürler :-)
VEYA Mapper

Saklanan anlık görüntüleri kullanarak geçmişi yeniden yapılandırmaktan bahseden tüm makaleler (bulabilirim) örnek alıyor. Bu hareket için de geçerli mi? Hareket resimülasyonunun, diğer oyuncular için birbirleriyle çarpışabilecekleri bazı büyük farklılıklara yol açabileceğini hayal edebiliyorum. İki oyuncunun birbirine karşı hareket ettiğini ve bir tanesinin çarpışma noktasından birkaç adım öteye geçmeyi bıraktığını varsayalım. Biz resimulate dünya iki oyuncu çok farklı pozisyonları olacağını yani eğer bu durdurma komutları yüzünden geç gecikme geldiğinde
Lope

Bu ilginç bir soru. Maalesef kesin bir cevabım yok. Sanırım hareketlerin oyun için ne kadar kritik olduğuna bağlı; sadece başka birine çarptın mı ve hiçbir şey olmuyor mu? Bu durumda sunucu muhtemelen umursamıyor, bir tahmin hatası olarak görülüyor (hepimiz boğulma noktalarında olduğunu gördük, değil mi?). Diğer oyuncuyu temas halinde mi öldürüyorsunuz? Bu durumda doğru yapmak çok daha önemlidir ve resimüle etmeye değer olabilir. Bir noktada bazı paketleri "çok eski" olarak atmanız gerektiğini unutmayın, aksi halde herhangi bir zamanda potansiyel olarak t = 0'dan potansiyel olarak resimüle edersiniz.
ggambett

4

Bunu henüz uygulamadım (bu yüzden hemen göremediğim bazı sorunlar olabilir), ancak yardım etmeye çalışacağımı düşündüm.

İşte söylediğin şey:

Müşteri A, T0’a girdi gönderir

Sunucu T1’de giriş aldı

Tüm müşteriler T2’deki değişikliği alıyor

Ancak T2'de, müşteri tahminini kullanarak, Müşteri A şimdi T4'e uygun bir konumdadır.

Sunucu zamanı açısından düşünmek muhtemelen yararlı olacaktır. (Muhtemelen) enterpolasyonun nasıl çalıştığına çok benzer .

Her komut bir sunucu zamanı ile gönderilir. Bu sunucu zamanı bir maçın başında, sunucu onayını sorgulayarak, ping süresini telafi ederek belirlenir. İstemcide kendi yerel kene sayınız vardır ve gönderdiğiniz her komut sunucu tiklerine dönüştürülür (basit bir çıkarma işlemidir)

Ayrıca, müşteri her zaman "geçmişte" işlemektedir. Demek ki, müşterinin gördüğü dünyanın, sunucunun zamanının gerçekte ne olduğunun 100ms.

Öyleyse, örneğinizi sunucu zamanı ile değiştirelim (S ile gösterilir).

İstemci T0'da sunucu zamanı S0 ile girdi gönderir (tahmin ediyorum ki "sunucu zamanı eksi enterpolasyon zamanının gerçekten temsilidir"). Müşteri sunucudan yanıt beklemiyor ve hemen hareket ediyor.

Sunucu, T1’de giriş alır. Sunucu, istemcinin verdiği S0 sunucu zamanında müşterinin yetkili pozisyonunu bulur. Bunu müşteriye gönderir.

Müşteri, T2'deki yetkili pozisyonu alır (hala S0 sunucu zamanı belirtilerek). Müşteri önceki olayların değerinin geçmiş zaman miktarını takip eder (muhtemelen sadece tüm onaylanmamış tahminlerin kuyruğu).

Öngörülen pozisyon / hız / sunucunun S0'a geri gönderdiği her neyse, müşterinin S0'da depoladıklarından farklıysa, müşteri bunu bir şekilde ele alır. Ya oynatıcıyı eski pozisyonuna geri döndürerek ya da önceki girişi resmeden ya da belki de hiç düşünmediğim bir şeyle.


3
Geçmişte müşterinin oluşturduğu bit hakkındaki bit dışında hepsi doğru. Sunucuya göre, istemci aslında gelecekte render oluyor! Sunucu, her istemciden gelen bilgilerin eski olduğunu ve her müşterinin o zamandan beri zaten değişeceğini biliyor.
Kylotan

2

Aslında github'da bunun nasıl yapıldığını gösteren açık kaynaklı bir uygulama var. Lance.gg göz atın

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

Müşteri tahmin kodu adı verilen modülde uygulanır. src/syncStrategies/ExtrapolateStrategy.js

Ekstrapolasyonun yanı sıra yukarıda bahsetmediğim iki kavram var:

  1. Artımlı Bükme. Temel olarak sunucu düzeltmesini bir kerede uygulamak yerine delta'nın küçük artışlarla uygulanmasına izin verirsiniz. Bu şekilde uzak nesneler yavaş yavaş sunucu konumlarına uyacak şekilde konumlarını ayarlayacaktır. Konum bükme, hız bükme, açı bükme ve açısal hız bükme vardır. Ayrıca farklı nesneler için farklı bükme faktörleri isteyebilirsiniz.
  2. Adım Yeniden yürürlüğe girme. Verilerin geçmişte olduğu gerçeği, zamanı sunucu veri zamanına geri alabileceğiniz ve bu noktadan yeniden başlayabileceğiniz anlamına gelir. Tabii ki, atlamak yerine, yeni bulunan pozisyona doğru bükülmeye ihtiyacınız olacak.

1

A İstemcisi her zaman sunucunun önündedir - ancak önemli değil. Sadece sunucu rapor edilen pozisyonda bir sorun olduğunu söylerse istemciyi geri çekmeniz gerekir, bu noktada müşteri düzeltilen değerlerde hata yaptıktan sonra yaptığı tüm değişiklikleri yeniden çalıştırır, uyumlu duruma getirmek için sunucu ile.

Bunu yapmak için, müşterinin bazı geçmiş durumunu ve geçmiş güncellemelerini hatırlaması gerekir. Bu sadece pozisyon, hız, oryantasyon, böyle bir şey gibi birkaç basit değer olabilir. Sunucu periyodik olarak çeşitli müşteri güncellemelerinin okunaklı olduğu ve bu nedenle müşteriden unutulabilecekleri konusunda bir onay gönderir. Ancak sunucu bir güncellemenin geçersiz olduğunu bildirirse, istemci durumu bu noktaya geri döner ve gelecekteki değişiklikler bu değiştirilmiş duruma uygulanır.

Valve makalesinin altında okunmaya değer bazı ekstra bağlantılar var - bunlardan biri: https://developer.valvesoftware.com/wiki/Prediction


Öyleyse, müşterinin (at t=4) hakkında bilgi aldığını düşünmekte haklıyım t=2, bu yüzden durumu t=2yeniden başlatır ve ardından nesneleri nesnelerden almak t=2için güncelleştirmeleri yeniden çalıştırır t=4?
George Duckett,

Hala bir sebepten dolayı anlayamıyorum. Sunucuya, oynatıcının konumu söylenmiyor, sadece girdiler var. Böylece oyuncu, sunucunun bulunduğu son konumdan hareket ediyor. Giriş uygulanır. Sunucu bilgilendirildi. Sunucu herkese girişi onaylar. Tüm komutların kabul edildiği varsayıldığında, sunucu hala Müşteri A'nın arkasında olacak - yani Müşteri A durduğunda, karakteri hemen duracak ve dur onayını aldığında sunucu konumuna geri dönecektir.
Chris Evans

@GeorgeDuckett: evet (t = 4 olması gerekmese de, herhangi bir tutarsızlık tespit edildiğinde olabilir ve herhangi bir sayıda yeniden yapılan güncelleme olabilir.)
Kylotan

@ChrisEvans: bilinen durum + girdilere dayalı değişiklikler yine de gönderme durumuna eşittir. Durdurma örneğine gelince, bu kendi başına bir girdidir ve sunucu bu girdiyi alana kadar hareketi simüle ediyor. Sürekli gecikme varsayarak, sunucu oynatıcının tam olarak hareket etmeyi durdurduğunda, istemcinin sunucunun önünde olduğu için göreceği konumda durmasını sağlar. (Gerçek dünyada gecikme değişir, bu yüzden düzeltmek için biraz enterpolasyon
yaparsınız
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.