Oyun geliştirmek için saatleri ağ üzerinden nasıl senkronize edebilirim?


10

Çok zamana dayalı yönleri olan bir oyun yazıyorum. Ağ durakları ve paketleri geçmediğinde (ve paketin alınıp alınmadığı zaman) oyuncu konumlarının tahmin edilmesine yardımcı olmak için zaman kullanıyorum. Bu, bir oyuncunun bir yön seçmesi ve hareket etmeyi durduramaması açısından pacman tipi bir oyundur, böylece sistem mantıklıdır (veya en azından öyle olduğunu düşünüyorum).

Bu yüzden iki sorum var: 1) Ağda gecikme olduğundan başlangıçtaki oyunların saatlerini nasıl senkronize ederim. 2) Onları senkronize ETMEMEK ve sadece aynı olduklarını varsaymak TAMAM mıdır (kodum saat diliminden bağımsızdır). İnsanların saatlerini hile yapmak için değiştirecekleri süper rekabetçi bir oyun değil, ama yine de.

Oyun Java ve Python'da programlanıyor (bir proje olarak paralel geliştirme)



5
Eminim bu soru zaten gamedev.stackexchange.com'da ya da en azından oradadır.
congusbongus

1
@CongXu: Çok emin değilim. Bu genellikle oyunlar için yapılan bir görev olsa da, doğası gereği oyun geliştirmeye özgü değildir. Diğer birçok dağıtılmış sistem senkronize saate ihtiyaç duyar.
Jan Hudec

2
IPv4 seçeneği TIMESTAMP'ı kullanmayı denediniz mi? Daha fazla bilgi yer almaktadır linux.die.net/man/7/socket oradan için linux.die.net/man/3/cmsg küçük bir örnek programında ve daha sonra pdbuchan.com/rawsock/rawsock.html önce sonuncusu IPv6 bölümü.
ott--

2
Oyunlar (uygulamalar) sistem saatine dokunmamalıdır.
Monica'yı eski durumuna getirin - M. Schröder

Yanıtlar:


9

Ben kesinlikle olduğunu düşünüyorum değil Tamam synchornize saati sisteminde . Kullanıcı sistem ayarlarına dokunmanızı beklemez ve birçok sistem bile izin vermez.

İhtiyacınız olan tek şey, zaman damgasını bir tarafın saatinden diğer tarafın saatine dönüştürmek için bir korelasyona sahip olmaktır. Öte yandan, eğer oyuncu pozisyonlarını tahmin etmek için kullanmak istiyorsanız, bu korelasyonun oldukça hassas olması gerekir, en azından saniyenin yüzde birine kadar. Sistem saati , rastgele makineler arasında bu kadar iyi bir korelasyon olmayacaktır. Dolayısıyla, ağ bant genişliğini korumak için muhtemelen diğer iletilerinizde gömülü olan NTP temasında bazı varyasyonlar kullanarak korelasyonu kendiniz kurmalısınız.

Temel fikir, gönderdiğiniz her zaman damgası ile onu gönderdiğiniz zaman damgası ve diğer taraftan son paketi aldığınızda sıra numarası ve zaman damgası olabilir. Buradan gidiş dönüşü hesaplarsınız: Örneğin, paket Q 1000'de gönderildiğini ve paket P 500'de alındığını söylüyorsa, 0'da paket P gönderdiğinizde ve 800'de Q aldığınızdan, gidiş dönüş (800-0) olur. ) - (1000 - 500) = 300. Asimetri bilmenin bir yolu yoktur, bu yüzden paketin her iki yönde yarım (150) keneler aldığını varsayarsınız. Ve bu uzak zaman damgası 1000 - (800 - 150) = 350 keneyle yerelin önünde. Gidiş-dönüş değişecektir. Saatin makul derecede hassas olduğunu varsayarsanız, korelasyonun uzun vadeli bir ortalamasını kullanmalısınız.

Saat için sistem saatini de kullanmak istemediğinizi unutmayın. Yarı yolda yeniden senkronize edilebilirler ve sizi yoldan çıkarabilirler. Sen kullanmalıdır clock(CLOCK_MONOTONIC)Unix veya GetTickCount(değil emin bu API'ler şu anda Java veya Python sarılmış nasıl) Windows üzerinde.


Not: SO_TIMESTAMPSoket seçeneği ( soru üzerine yorumda ott- tarafından belirtilen sokete (7) bakın ) , paketleri alan olay döngüsünün gecikme etkisini ayırmak için yararlı olacaktır. Çabaya değip değmeyeceği, ihtiyacınız olan hassasiyete bağlıdır.


1

Hangi oyuncunun saatinin doğru olduğunu nasıl anlarsınız? Yapmazsınız, bu yüzden bir referans saat kullanın .

NTP burada aşırıya kaçtı - sadece ~ 1 saniye hassasiyete ihtiyacınız var - bu yüzden rdate kullanın veya birçok saat senkronizasyon algoritmasından birinden bir şey seçin .

Bir yöntem seçtiğinizde, her oyuncunun makinesine bu yöntem başına zamanı almasını sağlayın (sistem saatini değiştirmeden). Referans UTC saati ile oyuncuların sistem saati UTC saati arasındaki fark ne olursa olsun, etkili ofsetleri. Bot hareketlerini veya ışın izi mermilerini zamanlamak için zamanla ilgili hesaplamalar yaptığınızda, sistem saatini aldıktan sonra bu ofseti hesaba katmış olursunuz. UTC kullanmak saat dilimi faktörlerini ortadan kaldıracaktır.


1

İkinci ifadeleri kullanmamanız ya da bunun için sistem saatinin yakınına gitmemeniz gerektiğini ifade ediyorum. Bu gereksinimi gerçekten incelerseniz, aşağıdaki gereksinimlere sahip olduğunuzu göreceksiniz:

  • Önceki kareden bu yana ne kadar zaman geçtiği, böylece herhangi bir zaman tabanlı öğeyi ilerletebilirsiniz. Her ikisi de farklı hızlarda işaretlerse bu, istemci ve sunucuda farklı olabilir (örneğin, sabit bir 20Hz'de (veya her neyse) çalışan sunucuları, ancak istedikleri kadar hızlı çalışmasına izin verilen istemcileri görebilirsiniz).
  • Mevcut harita başladığından bu yana ne kadar zaman geçti. Bu sıfır tabanlı bir zamanlayıcıdır (başlangıçta hem istemci hem de sunucuda 0 olarak başlatır) ve sunucu zamanı "ana" olarak kabul edilir, böylece sunucu bu zamanın mevcut görünümünü her çerçeve için istemciye gönderir sunucuda çalışır. Bu, geçerli sunucu zamanını alarak ve sunucunun başladığı zamanı çıkararak veya yukarıdaki kare başına süreleri biriktirerek gerçekleştirilebilir. Yukarıdaki istemci tarafı kare başına süre, art arda herhangi iki sunucu çerçevesi arasında enterpolasyon noktaları oluşturmak için de kullanılabilir.
  • Diğer tüm zamanların ilerlediği bir referans "temel süre"; bu hem istemcide hem de sunucuda aynı olabilir (ancak tüm oyun türleri için kesinlikle gerekli değildir) ve oyunun başında (veya geçerli harita) başlatılır, ancak daha sonra asla değiştirilmez (yeni bir oyun veya yeni harita olmadıkça) - Başladı).

Bu basitleştirilmiş bir taslaktır - Gecikme / bırakılan paketler / vb. Gibi sorunlarla uğraşmaya çalışmıyorum - ancak her şeyin temel alınması gereken temel çerçevedir.

Son öğe olmasına rağmen bu ihtiyaçları hiçbiri, sistem saatinin yanında gitmek veya farklı zaman dilimleri gibi konularda ilgili olması olabilir istenirse bir zaman dilimini kullanır. Önemli olan, geçen geçen sürelerin yüksek çözünürlüklü sıfır tabanlı bir zamanlayıcı kullanılarak ölçülmesidir, bu nedenle zaman dilimi farklılıklarına karşı tamamen agnostiktirler. Sunucuda gerçek zamanı bulmak ister misiniz? Sadece geçen zamanı referans taban zamanına ekleyin ve anlayın. Aynı şekilde müşteri için.

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.