Quake 3 gibi hassas ağ bağlantılı oyunlar için sunucu-istemci saatlerini senkronize halde nasıl tutabilirim?


15

2B yukarıdan aşağıya atıcı üzerinde çalışıyorum ve Quake 3 gibi ağ bağlantılı oyunlarda kullanılan kavramları kopyalamak için elimden geleni yapıyorum.

  • Yetkili bir sunucum var.
  • Sunucu istemcilere anlık görüntüler gönderir.
  • Anlık görüntüler bir zaman damgası ve varlık konumları içerir.
  • Varlıklar anlık görüntü konumları arasında enterpole edilir, böylece hareket düzgün görünür.
  • Gerektiğinde, varlık enterpolasyonu "geçmişte" biraz gerçekleşir, böylece aralarında enterpolasyon yapmak için birden fazla anlık görüntü elde ederiz.

Karşılaştığım sorun "saat senkronizasyonu".

  • Basitlik için, paketleri sunucuya ve sunucudan aktarırken sıfır gecikme olduğunu bir an için yapalım.
  • Sunucu saati istemci saatinden 60 saniye ilerideyse, anlık görüntü zaman damgası, istemci yerel zaman damgasından 60000 ms önde olacaktır.
  • Bu nedenle, varlık anlık görüntüleri, istemci herhangi bir varlığın hareketlerini gerçekleştirdiğini görmeden önce yaklaşık 60 saniye boyunca toplanır ve oturacaktır, çünkü müşteri saatinin yakalanması uzun zaman alır.

Bir anlık görüntü alındığında sunucu ve istemci saati arasındaki farkı hesaplayarak bunu aşmayı başardım.

// For simplicity, don't worry about latency for now...
client_server_clock_delta = snapshot.server_timestamp - client_timestamp;

Varlığın enterpolasyonda ne kadar ilerlediğini belirlerken, farkı müşterinin şimdiki zamanına eklerim. Bununla birlikte sorun, sarsıntıya neden olacağı, çünkü iki saat arasındaki fark, diğerlerinden daha hızlı / daha yavaş gelen anlık görüntüler nedeniyle aniden dalgalanacaktır.

Saatleri, algılanabilir tek gecikmenin enterpolasyon için sabit kodlanmış ve normal ağ gecikmesinden kaynaklanan gecikme olacağı kadar nasıl senkronize edebilirim?

Başka bir deyişle, saatler önemli ölçüde senkronize olmadığında, sarsıntı olmadan, enterpolasyonun çok geç veya çok erken başlamasını nasıl önleyebilirim?

Düzenleme: Vikipedi göre , NTP internet üzerinden saatler birkaç milisaniye içinde senkronize etmek için kullanılabilir. Ancak, protokol karmaşık görünüyor ve belki de oyunlarda kullanım için aşırı mı?


nasıl karmaşık ? Her biri iletim ve varış zaman damgaları ile bir istek ve yanıt, daha sonra delta almak için biraz matematik
cırcır ucube

@ratchetfreak: Göre ( mine-control.com/zack/timesync/timesync.html ) 'e göre, Ne yazık ki, NTP çok karmaşık ve daha da önemlisi, doğru zaman deltasında birleşmek için yavaş. Bu, NTP'yi ağ için ideal olandan daha az yapar oyuncunun bir oyun hemen başlamasını beklediğini oyun ..."
Joncom

Yanıtlar:


10

Etrafta arama yaptıktan sonra, 2 veya daha fazla bilgisayarın saatlerini senkronize etmek önemsiz bir görev değil gibi görünüyor. NTP gibi bir protokol iyi bir iş çıkarır ancak oyunlarda pratik olamayacak kadar yavaş ve çok karmaşıktır. Ayrıca, benim için çalışmayan UDP kullanıyor çünkü UDP'yi desteklemeyen web soketleriyle çalışıyorum.

Ancak burada nispeten basit görünen bir yöntem buldum :

Saatleri birbirinin 150ms (veya daha iyisi) içinde senkronize ettiğini iddia ediyor.

Bunun amacım için yeterince iyi olup olmayacağını bilmiyorum, ancak daha kesin bir alternatif bulamadım.

İşte sağladığı algoritma:

Oyunlar için basit bir saat senkronizasyonu tekniği gereklidir. İdeal olarak, aşağıdaki özelliklere sahip olmalıdır: makul derecede doğru (150 ms veya daha iyi), yakınsama hızlı, uygulanması basit, TCP gibi akış tabanlı protokollerde çalışabilir.

Bu özelliklere sahip basit bir algoritma aşağıdaki gibidir:

  1. İstemci geçerli yerel saati "zaman isteği" paketinde damgalar ve sunucuya gönderir
  2. Sunucu tarafından alındığında, sunucu sunucu zamanını damgalar ve geri döner
  3. İstemci tarafından alındığında, istemci gönderilen zamanı gönderilen süreden çıkarır ve hesaplama gecikmesini ikiye böler. İstemci-sunucu zaman deltasını belirlemek için geçerli zamanı sunucu zamanından çıkarır ve doğru saat deltasını elde etmek için yarı gecikmeyi ekler. (Şimdiye kadar bu algothim SNTP'ye çok benziyor)
  4. İlk sonuç hemen saati güncellemek için kullanılmalıdır, çünkü yerel saati en azından doğru basketbol sahasına (en azından doğru saat dilimine!) Getirecektir.
  5. İstemci 1'den 3'e kadar olan adımları beş veya daha fazla kez tekrarlar ve her seferinde birkaç saniye duraklar. Arada başka trafiğe izin verilebilir, ancak en iyi sonuçlar için en aza indirilmelidir.
  6. Paket makbuzlarının sonuçları birikir ve en düşük gecikme süresinde en yüksek gecikme süresine göre sıralanır. Ortalama gecikme süresi, bu sıralı listeden orta nokta örneği alınarak belirlenir.
  7. Medyandan yaklaşık 1 standart sapmanın üzerindeki tüm numuneler atılır ve kalan numunelerin ortalaması aritmetik bir ortalama kullanılarak alınır.

Bu algoritmanın tek inceliği, medyanın üzerinde bir standart sapmanın üzerindeki paketlerin atılmasıdır. Bunun amacı TCP tarafından yeniden iletilen paketleri ortadan kaldırmaktır. Bunu görselleştirmek için TCP üzerinden beş paketlik bir örnek gönderildiğini ve yeniden aktarım olmadığını hayal edin. Bu durumda, gecikme histogramında ortalama gecikme süresi etrafında tek bir mod (küme) olacaktır. Şimdi başka bir denemede, beş taneden oluşan tek bir paketin yeniden iletildiğini düşünün. Yeniden aktarım, bu bir örneğin, gecikme histogramında ortalama olarak birincil modun ortalamasının iki katı kadar sağa düşmesine neden olur. Medyandan bir standart sapmadan daha fazla düşen tüm örnekleri keserek, bu kaçak modlar, istatistiklerin büyük kısmını içermedikleri varsayılarak kolayca ortadan kaldırılır.

Bu çözüm, sorumu tatmin edici bir şekilde iyi yanıtlıyor gibi görünüyor, çünkü saati senkronize ediyor ve sonra duruyor ve zamanın doğrusal olarak akmasına izin veriyor. İlk yöntemim saati sürekli güncellediğinden anlık görüntüler alınırken zamanın biraz atlanmasına neden oldu.


Bu sizin için nasıl işe yaradı? Şimdi aynı durumdayım. Yalnızca TCP'yi destekleyen bir sunucu çerçevesi kullanıyorum, bu nedenle UDP datagramlarını gönderen NTP'yi kullanamıyorum. TCP üzerinden güvenilir zaman senkronizasyonu yaptığını iddia eden herhangi bir Zaman Senkronizasyon Algoritması bulmakta zorlanıyorum. Ancak bir saniye içinde senkronizasyon ihtiyaçlarım için yeterli olacaktır.
dynamokaj

@dynamokaj Oldukça iyi çalışıyor.
Joncom

Güzel. Uygulamayı paylaşabilmeniz mümkün mü?
dynamokaj

@dynamokaj Şu anda aklıma gelen hiçbir projede böyle bir uygulama bulamıyorum. Alternatif olarak, benim için yeterince işe yarayan şey: 1) bir ping isteğinden / yanıtından hesapladığınız gecikmeyi hemen kullanın ve daha sonra, 2) yeni değere doğru gelecekteki tüm bu yanıtlar için anında değil, kademeli olarak kullanın. Bunun benim amacım için çok doğru olan bir "ortalama" etkisi var.
Joncom

Sorun değil. Arka uç hizmetimi Google App Engine'de çalıştırıyorum, bu nedenle sunucuların Google NTP Sunucusu kullanılarak senkronize edildiği Google altyapısında: time.google.com ( developers.google.com/time ) Bu nedenle Xamarin Mobile istemcim için aşağıdaki NTP istemcisini kullanıyorum istemci ve sunucu arasındaki farkı elde etmek için. components.xamarin.com/view/rebex-time - Yanıtlamak için zaman ayırdığınız için teşekkür ederiz.
dynamokaj

1

Temel olarak, [tüm] dünyayı düzeltemezsiniz ve nihayetinde çizgiyi çizmeniz gerekir.

Sunucu ve tüm istemciler aynı kare hızını paylaşıyorsa, yalnızca bir gecikme olayından sonra bağlandığında ve daha sonra zaman zaman eşitlenmeleri gerekir. Gecikme, zamanın akışını veya PC'nin bunu ölçme yeteneğini etkilemez, bu nedenle, enterpolasyon yerine birçok durumda, tahmin etmek zorundasınız. Bu eşit derecede istenmeyen etkiler yaratır, ancak yine de budur ve mevcut tüm kötülüklerden en azını seçmelisiniz.

Birçok popüler MMO'da, geride kalan oyuncuların görsel olarak açık olduğunu düşünün. Bunların yerinde, doğrudan bir duvara doğru koştuğunu görürseniz, müşteriniz tahmin ediyordur. Müşterinizin yeni verileri alındığında, oynatıcı (istemcilerinde) önemli bir mesafe kat etmiş olabilir ve "lastik bant" veya yeni bir yere ışınlanır (bahsettiğiniz "sarsıntı"?). Bu, büyük, marka markalı oyunlarda bile olur.

Teknik olarak, bu oyunun değil oyuncunun ağ altyapısıyla ilgili bir sorundur. Birinden diğerine gittiği nokta çizmeniz gereken çizgidir. Kodunuz, 3 ayrı bilgisayarda, aşağı yukarı aynı süreyi kaydetmelidir. Bir güncelleme almazsanız, Update () kare hızınızı etkilemez; bir şey varsa, muhtemelen daha az güncellenmesi gerektiğinden daha hızlı olmalıdır.

"Eğer crummy internet varsa, bu oyunu rekabetçi oynayamazsınız."
Bu bir kova ya da bir hata değil.

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.