Çok oyunculu platform oyunu - Sunucudaki düzeltmeler normalde sunucudaki tek bir istemcide gerekli mi?


10

Şu anda oldukça basit bir çok oyunculu platform üzerinde çalışıyorum. Gecikmeyi gizlemek için kullanılan tekniklerle ilgili biraz makale okudum, ancak yine de kafamı belirli kavramların etrafından dolaşamıyorum. Konuyu çok ilginç buluyorum ve fikirleri kendim denemeyi seviyorum, ancak gamedev stackexchange'i sormamın sorum için daha verimli olacağını düşünüyorum. Mevcut durumumu ve yol boyunca hangi sorunun ortaya çıktığını anlatmak için elimden geleni yapacağım.

Şimdilik sadece bir oyuncunun sunucu ile senkronize edilmesini istiyorum. Teorik olarak, kendi başına müşteri tarafı tahmini olan bir oyuncunun, sunucu düzeltmelerini gerektirmeyeceğini varsaydım, çünkü hareketini etkileyen harici faktörler yoktur. Bu nedenle, prototipim şu anda sunucu düzeltmeleri gönderilmeden yalnızca bir oyuncunun bir sunucu ile senkronize edildi.

Oyun ağlarına aşina iseniz, sanırım bağlam bölümlerini atlayabilirsiniz, ancak yol boyunca da yanlış bir şey yapmış olabilirim.

İstemci döngüsü (çerçeve başına bir kez, ~ 16.67ms'de bir kez)

Basitleştirilmiş istemci döngüsü şöyle görünür:

  1. Yerel girişi (WASD) kontrol edin ve bunları eylem olarak paketleyin (örn. Type=MoveLeft, Time=132.0902, ID=15). Daha sonra göndermek için paketlenmiş eylemleri saklarız. Ayrıca, istenen eylemi doğrudan oyunun yerel fizik simülasyonuna uygularız. Örneğin, bir MoveLefteylemimiz varsa , oyuncunun hızında sola doğru bir kuvvet uygularız.

  2. İşlem göndermek için işaretleyin. İstemcinin bant genişliğini kötüye kullanmasını önlemek için, paketlenmiş eylemleri yalnızca belirli aralıklarla (örn. 30 ms) gönderin.

  3. Sunucu değişikliklerini uygulayın. Belli bir noktada bu, sunucu tarafından alınan deltaları ve düzeltmeleri ele alır ve bunları oyunun yerel simülasyonuna uygular. Bu özel soru için bu kullanılmaz.

  4. Yerel fiziği güncelleyin. Ana oynatıcıda fizik döngüsünü çalıştırın. Temel olarak, bu oyuncunun hareketinin müşteri tarafı tahminini yapar. Bu, oyuncunun hızına yerçekimi ekler, oyuncunun hızını konumuna uygular, yol boyunca çarpışmaları giderir, vb. .

Fizik ve diğer bölümlerle ilgili birkaç ayrıntıyı atlıyorum çünkü soru için gerekli olmadıklarını hissediyorum, ancak soru ile ilgili olup olmadıklarını bana bildirmekten çekinmeyin.

Sunucu döngüsü (15ms'de bir)

Basitleştirilmiş sunucu döngüsü şöyle görünür:

  1. Eylemleri ele alın. İstemcilerden alınan eylem paketlerini kontrol edin ve sunucu fizik simülasyonuna uygulayın. Örneğin, 5 MoveLefteylem alabilirdik ve kuvveti hıza 5 kez uygularız . Bir eylem paketinin tamamı , eylem gerçekleşir gerçekleşmez uygulandığı istemciye bir "çerçeve" üzerinde yürütüldüğünü belirtmek önemlidir .

  2. Oyun mantığını güncelleyin. Oyun fiziğini, oyuncuları hareket ettirme ve çarpışmalar, vb.

  3. Düzeltmeleri gönderin. Yakın zamanda değiştiyse düzenli olarak (örneğin her 35ms'de bir) diğer oyunculara (örn. Oyuncu pozisyonları, sağlık vb.) Delta gönderiyoruz. İstemci tarafı tahmininin iyi çalıştığından emin olmak için tek bir oyuncunun simülasyonunun istemci ve sunucuda düzeltmeler olmadan aynı sonuçları vermesini istediğim için şu anda uygulanmadı.

Sorun

Mevcut sistem basit koşullar altında iyi çalışıyor ve basit yatay hareketlerle çok benzer sonuçlar verdiğini görmekten mutluluk duydum (yanlışlıklar kayan nokta hassasiyet hatalarından kaynaklanıyor, inanıyorum):

Senkronizasyon basit çarpışmalar / hareketlerle iyi çalışır

Lütfen prototip grafiklerini dikkate almayın. Beyaz dikdörtgen = oyuncu, Kırmızı dikdörtgenler = engeller, Mavi = arka plan

Ancak, zıplama ve yalıtılmış bir engele yaklaşma gibi zamana duyarlı hareketler yaptıktan sonra senkronizasyon hataları alıyorum:

Senkronizasyon çalışmıyor çünkü zamana duyarlı anlarda belirtilen engeli aştım

Teoride, müşterinin pozisyonunu etkileyen dış faktörler olmadığından, her ikisinin de her zaman aynı sonuçlarla sonuçlanmasını beklerdim. Ancak pratikte, sorunu anladığımı düşünüyorum.

Bunun gibi bir engelin etrafında zıplama, oyuncunun zamanlamasına çok bağlı olduğundan , pozisyona hızın ne zaman uygulandığına ilişkin küçük değişiklikler , sonuç üzerinde tekrarlar oluşturacaktır (örneğin, müşteri ile çarpışmayı önlemek için tam zamanında hareket edebilir. sunucu, daha sonra tüm eylem paketini alır ve bunu bitirir ve son sonucu değiştirerek küçük bir süre için engele takılı kalır). İstemcinin ve sunucunun nasıl işlediği arasındaki fark, esas olarak istemcinin tüm eylemlerini gerçekleştiği anda gerçekleştirmesidir, sunucu ise hepsini alırken toplu olarak yapar.

Soru

Bu uzun bağlam nihayetinde sorumu doğuruyor (şimdiye kadar okuduğunuz için teşekkür ederim): Sunucuyla senkronize edilen tek bir oyuncu olsa bile sunucu düzeltmeleri yapılması normal mi, yoksa zamana duyarlı durumlarda senkronizasyondan kaçınmak için belirli teknikler kullanmalı mıyım ?

Bazıları ile daha az rahat olduğum bazı olası çözümleri düşündüm:

  1. Sunucu düzeltmesini uygulayın. Bunun normal bir davranış olduğunu varsayalım ve hataları düzeltin. Yine de uygulamak istedim, ama şimdiye kadar yaptığım şeyin kabul edilebilir olduğundan emin olmak istedim.

  2. İstenen eylemleri uygulamak için sağlanan müşteri zamanını kullanın. Sanırım bu gecikme telafisine benzer, "zamanda geriye gitmeyi" ve hareketi kontrol etmeyi gerektirir. Sunucu düzeltmelerini uygulamak gibi, zaman içinde geri gidin ve bundan sonraki eylemleri yeniden uygulayın. Fikirden gerçekten hoşlanmıyorum. Kaynaklarda karmaşık, pahalı görünüyor ve müşterinin verilen zamanına güvenmeyi gerektiriyor (ancak zamanın nispeten yasal görünüp görünmediğini kontrol etmeyi planlasam da).

  3. GameDevelopment StackExchange'ten tüm sorunlarımı çözecek yepyeni bir fikir isteyin.

Sadece oyun ağı dünyasında başlıyorum, bu yüzden lütfen yukarıdaki kavramlardan herhangi birini düzeltmekten / eleştirmekten / hakaret etmekten veya Harika Ağ Dünyası'ndaki yolculuğumda bana yardımcı olabilecek fikirler / kaynaklar vermekten çekinmeyin. Affedersin, cevabımı başka bir yerde bulabilirsem, bu konuda başarısız oldum.

Değerli zamanınız için çok teşekkür ederim.


Sunucunuz ve istemciniz çerçeveleri farklı hızlarda çalıştırır. İstemci art arda gelen karelerde iki eylem gerçekleştirir, ancak sunucu aralarında bir kare boşluk görürse ne olur?
user253751

off kendimi tabanlı @immibis gafferongames.com/game-physics/fix-your-timestep bu etkiyi en aza indirmek için.
Jesse Emond

Yanıtlar:


11

Bu gibi durumlarda, istemcinin biraz yetkili olmasına izin vermek daha iyi olabilir. Bu hassas kontroller için, gerçekten gelişmiş düzeltme ve tahminlerde bile iyi davranışlar elde etme olasılığınız çok düşüktür.

Müşteri sadece "Ben atladım" mesajlarını göndermekten "T zamanında X, Y'den atladım" mesajlarını göndermeye kadar uzanmalıdır. Sunucu daha sonra hile karşı korumak için konumun oyuncunun T zamanında (geçmişte oldukça küçük bir zamanla sınırlandırabilirsiniz) olduğunu düşündüğü şeye yakın olduğunu kontrol eder, ardından istemcinin bulunduğu konumdan atlamayı simüle eder gönderdi. Sunucu, istemciyi yalnızca sıkışmadan uzak olduğunda düzeltir (genellikle gecikme veya benzeri nedeniyle).

Bu tür teknik, oyunun yerel istemcide duyarlı hissetmesini ve uzak istemciler için pürüzsüz görünmesini sağlamak için düzeltme ve enterpolasyon ile birlikte kullanılır.


Çok ilginç. Bunu uygulamaya çalışacağım ve nasıl gittiğini göreceğim. Cevaplamak için zaman ayırdığınız için çok teşekkür ederim. Bu arada, "yakın mesafede" ve "geçmişte oldukça küçük bir zaman" dan bahsettiniz, sırasıyla sabit bir mesafe ve zamanla kontrol eder misiniz? Veya pozisyonların geçmişini tutmak ve müşterinin ortalama Gidiş-Dönüş Süresini (ya da başka bir şeyi) kullanmak gibi daha karmaşık teknikler mi kullanacaksınız?
Jesse Emond

Oyununuz için ne işe yararsa. Basit başlayın, sadece gerekli bulduğunuz derecede karmaşıklaştırın. Bazı sunucular ~max(RTT), geçmişte sunucu keneleri için bir tür geçmişini tutarlar , ancak oyununuz için özel olarak gerekip gerekmediğini bilmiyorum. Ayrıca, istemcide bir miktar vuruş / atış algılaması yapmak istediğiniz ve sadece bir oyuncunun 46ms önce nerede olduğunu değil, aynı zamanda hedefinin 46ms önce nerede olduğunu ve nerede olduğunu da bilmek istediğiniz shooter tarzı oyunlar için daha kullanışlı olabilir. hareketli oklüzyon platformları.
Sean Middleditch

Mükemmel. Neyin en iyi olduğunu deneyeceğim ve göreceğim. Kabul edilen cevap olarak işaretleme, tekrar teşekkürler!
Jesse Emond
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.