Bir istemci / sunucu gerçek zamanlı video oyununda daha hızlı bilgisayarlarla nasıl başa çıkılır?


15

Socket.io kullanarak ilk çevrimiçi oyunumu oluşturuyorum ve bunun agar.io veya diep.io gibi gerçek zamanlı çok oyunculu bir oyun olmasını istiyorum.

Ama tüm bilgisayarları aynı hızda nasıl çalıştıracağımızı anlamaya çalışıyorum.

Modeller için üç fikrim var, ancak hiçbiri doğru görünmüyor ve normal video oyunlarının nasıl yaptığını merak ediyorum. (Fikirlerimi okumayı atlayabilirsiniz; size yaşadığım sorunları görmeniz için bir yol sunarlar.)

  1. Sunucu, istemcilerin kendi başlarına çalışmasına ve sunucuya güncellemeleri iletmesine izin verir, bu da onları diğer istemcilere yayınlar. Bu, bazı bilgisayarların diğerlerinden daha hızlı çalıştığı ve daha hızlı güncelleme yapmalarına ve ekran boyunca daha hızlı hareket etmelerine izin verme sorununa sahiptir.

  2. Sunucudan istemcilere ne zaman güncelleme yapılacağını söyleyin. Daha sonra son müşteri yanıt verene kadar bekleyebilirim (bir kişinin bilgisayarının yavaş olması durumunda korkunç bir fikir), ilk istemci yanıt verene kadar bekleyebilirim (yine, her çerçeveden önce iletişim bekleniyor) veya sadece olabildiğince hızlı gönderebilirim ( 1 numarayla aynı sorunla karşılaşıyor gibi görünüyor).

  3. Oyunun başında, sunucuya müşterilere ne kadar hızlı güncelleme yapılacağını söyleyin. Bu, müşterinin o zaman aralığındaki hareketi kısıtlamaktan sorumlu olacağı anlamına gelir. Örneğin, birisi bu süre içinde bir şekilde iki kez bir düğmeye basmayı başarırsa, yalnızca bir düğmeye basma olayı gönderir. Bu, bazı eylemlerin göz ardı edilmesi (çift düğmeye basma gibi) ve etkileşimin, sunucunun saatiyle eşleşmeyebilecek istemcinin saatine dayanması sorunudur. Sunucunun her istemciyi takip etmesi ve güncellemelerinin doğru zamanda gönderildiğinden emin olması gerekir.

Biraz araştırma yaptım , ancak okuduğum makaleler, bir istemci diğer istemcilerden daha hızlı güncellemeler gönderirse ne yapacağını özellikle ele almıyor gibi görünüyor.

Benim özel durumumda, daha yüksek klavye hızlarına sahip kişilerle uğraşıyorum (bilgisayarları diğer bilgisayarlardan daha fazla klavye güncellemesi gönderir).

Programcılar genellikle bununla nasıl ilgilenir?


1
Benim tecrübelerime göre, değiller. Bu yüzden oyun makineleri var; son teknoloji alev atıcısı için 5 bin dolar ödeyenlerin otomatik olarak hala Commodore 64 kullananlardan avantajı var.
Robert Harvey

1
Yani oyunum yavaş görünecek çünkü en düşük ortak paydada oynamak zorunda mıyız? Görünüşe göre oyun sunucusu tempoyu ayarlamalı ve takip etmek istemcilere kalmış ya da sadece gecikmeniz gerekecek.
JeffO

3
Soruyu yanlış anlayabilirim, ancak kene tabanlı bir istemci ve sunucu modeli kullanmak muhtemelen peşindesinizdir. gamedev.stackexchange.com/questions/81608/… Temel olarak sadece giriş ve mantığı her X zamanında işlersiniz (genellikle 1 / N saniye, 60Hz mantık için 1/60 gibi)
Christopher Wirt

4
Soruyu biraz daha okuduktan sonra, oyunun müşteri yönlerine çok fazla odaklanmışsınız gibi görünüyor. "Adil" bir çok oyunculu oyun istiyorsanız, sunucunuzun yetkili olması gerekir. Bu, istemcilere olan her şeyin sunucu tarafından doğrulandığı veya yapıldığı anlamına gelir. Sonra, muhtemelen yukarıdaki gibi kene tabanlı bir sistem aracılığıyla işleri kısıtlıyorsunuz.
Christopher Wirt

1
Ah, gerçek zamanlı net kod. Oyun geliştirmenin en derin, en karanlık yeri. Gemiye hoţgeldin dostum!
T. Sar

Yanıtlar:


8

Üçüncü fikriniz, bu tür bir soruna endüstri çözümü olarak düşündüğüm şeylere en yakın olanı gibi görünüyor.

Tanımladığınız şey genellikle Keneler olarak adlandırılır . Her bir işarette, seri halinde her istemci için sabit sayıda eylem işlenir. Çoğu zaman, oyun sunucularının yetenekli olduklarında bazı paralel eylemleri olacaktır, ancak bu çok daha karmaşık bir sorundur.

Bir kene muhtemelen 1 / N saniye şeklinde olacak, N saniyedeki kene sayısı veya Tickrate olacaktır. Kullanım durumunuza bağlı olarak bu tickrate çok sık veya çok seyrek olabilir. Benim kişisel önerim, daha fazlasına ihtiyacınız olmadığından emin olmadan saniyede 60 kenenin üzerinde bir tickrate önlemek olacaktır. Muhtemelen bilmiyorsunuz :)

Eylemler atomik olmalıdır. Örneğin, slither.io'da, vurmak gibi bir oyuncu harekete geçmedikçe, hareket etme gibi bir eylem, zincirinizi kırmak gibi bir şeyi hemen işlememelidir. Bu, piksel düzeyindeki bir şey için önemsiz görünebilir, ancak karo tabanlı hareketle uğraşıyorsanız, çok daha belirgin hale gelir ve adalet sağlar. Oyuncu A döşemesi X, Y'ye ve Oyuncu B şu döşemede bulunuyorsa, işaretin sonunda, oyuncu B'nin aralarında herhangi bir eylem gerçekleştirmesi için yine de bu döşemede olduğundan emin olmalısınız.

Ayrıca, bağımsız olarak sunucu tarafında yapılmadıkça, hesaplamalarınızın herhangi birinin istemci tarafında yapılmasından kaçının diyorum. Bu, fizik ile karmaşık ve pahalı hale gelir (birçok oyun, bu nedenle fizik için diğer birçok eylem ve olaydan daha düşük bir kene oranı seçer)

Referans olarak, burada kendi oyun sunucuları ve çok oyunculu ağ anlayışınızı desteklemek için iyi bir bağlantı .

Son olarak, adilliğin sunucunuzu mahvetmesine izin verme diyorum. Oyununuzun haksız olmasına neden olan istismarlar varsa bunları düzeltin. Küçük bir avantajı olan daha iyi bir bilgisayar meselesi ise, bunun bir anlaşma kadar büyük olmayabileceğini söyleyebilirim.


3
@ProQ, iyi bir net kod yazmanın önemsiz olmadığını not etmekte fayda var! Uygulamanız baştan beri iyi çalışmıyorsa ve net kodunuz emilmiş gibi görünüyorsa pes etmeyin. Her gün yaşamak için bunu yapan insanların bile onunla sorunları var. sadece bu kadar zor!
T. Sar

0

Aşağıdaki sistem, tüm istemcilerin ve sunucunun herhangi bir zamanda neredeyse aynı oyun durumunu paylaşmasını sağlar.

Oyunun durumunu hem istemci hem de sunucuda bulundurun.

İstemci bir komutu (fare, klavye, vb. Diğer girişler) kullanmaya çalıştığında, geçerliyse oyunun durumuna bakın.

Öyleyse, komutu gönderen istemcide çalıştırmadan sunucuya gönderin.

Sunucu komutu aldığında, geçerli ise oyunun durumuna bakın.

Eğer öyleyse, komutu sunucuda yürütülmesi bittikten sonra kesin tarihiyle TÜM istemcilere geri gönderin, ardından komutu istemcilere göndermek için minimum süreye eşit bir gecikmeden sonra komut tarafından istenen eylemleri yürütün . daha sonra tarihi kaydedin, bu geleceğin tahmin edilmesine yardımcı olur. Zaman çok değişiyorsa, oyun sisteminizi daha kararlı hale getirin.

Bir istemci sunucudan bir komut aldığında, geçerliyse oyunun durumuna bakın, komut tarafından istenen eylemleri hemen yürütün, ardından geçerli tarihe bakın ve alınan tarih tahminiyle karşılaştırın. Geçerli değilse istemci senkronize değil. (Benzer bir bağlantıya sahip tüm istemciler aynı anda alınır)

Tarih daha önce ise, önceki adımda bir sorunla karşılaşırsınız, düzeltin. Tarih biraz sonra bir şey yapmazsa, Tarih uzun bir süre sonra ise, istemci senkronize değil, yani istemci çok geride kalıyor.

Bir istemci senkronize olmadığında, sunucunun tüm oyun durumunun bir kopyasını isteyin ve bunu kullanın. Bu çok sık gerçekleşirse, komut göndermekten daha pahalı olduğu için bunu düzeltin.

İstemcilerde, SADECE yapacak başka bir şey kalmadığında ekranda bir şeyler oluşturun. Basit senaryolarda, oluşturma işlevi yalnızca geçerli oyun durumunu girdi olarak alır.

Bunun da ötesinde, öngörücü sistemleri, gruplama komutlarını, yalnızca farkları oluşturma vb.

Doğrulama farklı olmalı, örneğin, komut isteklerini / zaman birimini sınırlamak sunucuya bağlıdır.


0

Bunun kullandığınız kütüphane veya ortam sorunu olup olmadığını bilmiyorum, ama bence bu tamamen yanlış.

Çok oyunculu oyunların büyük çoğunluğunda, gerçek hesaplamalar yapan sadece sunucudur. Müşteriler sadece gerçek performans probleminin 3D grafikler çizdiği aptal IO makineleridir. Ve bu durumda, istemcinin 20 veya 200 FPS'de çalışıp çalışamayacağı önemli değildir, çünkü bu sadece görselleri etkiler. Bu "istemci güncellemesi" nin kesinlikle bir anlamı olmadığı anlamına gelir. İstemci, sunucunun neyi hesaplayabileceğini "tahmin etmeye" çalışabilir, ancak bu sadece oyun hissini düzeltmek içindir ve oyunun kendisi üzerinde gerçek bir etkisi yoktur.

daha yüksek klavye hızları

Bunun ne anlama geldiğini bile bilmiyorum. Çoğu insan düşük kaliteli klavyelerin hızına bile yetişemez, bu yüzden oyuncuların performansını nasıl etkiler?

Aksi takdirde, soru çok geniş görünüyor ve bunun yerine, sahip olamayacağınız "genel" sorunu telafi etmek yerine, tek bir gerçek probleme odaklanmalısınız.


daha yüksek klavye hızları yazmakla ilgili değildir, "ileri hareket" tuşunu veya "ateş" tuşunu basılı tutarsanız kaç komut gönderilebileceği ile ilgilidir.
gbjbaanb

@gbjbaanb Peki bu nasıl bir problem? Sadece basılan ve bırakılan komutları önemsemelisiniz. Güncellemenin ne kadar hızlı olduğu umurumda değil.
Euphoric

İstemcide OP gibi tüm olayları idare edip etmediğinizi önemsiyorsunuz. Yani w tuşuna basarsanız biraz ileri gidersiniz ve klavyeniz başkasınınkinden daha hızlıysa onlardan daha hızlı gidersiniz. İstediğiniz son şey, ilerlemek için bir tuşa basmaya devam etmeniz gereken bir yarış oyunu yapmaktır!
gbjbaanb

@gbjbaanb Hayır. Bu yanlış. Sunucu "oyuncu ileri gidiyor" ve sonra her saniyenin 1 / 60'ında TÜM oyuncuların ilerlemeye bağlı olarak konumlarını günceller. TÜM oyunlar böyle çalışır. Güncelleme döngüsü oyundaki tüm varlıklar için aynıdır ve güncellemeler kullanıcı arayüzündeki olaylara dayalı DEĞİLDİR.
Euphoric

1
Hayır, OP'nin anlayışı bu değildi, bu yüzden ona sordu ve bu yüzden "Bunun ne anlama geldiğini bile bilmiyorum" dedin. OP'nin pozisyonunu anlarsanız, sorusu mantıklıdır. OP, oyununu tamamen istemciden ne kadar hızlı olayların dağıtıldığına bağlı olarak bir oyun döngüsü ile çalışacak şekilde kodladıysa, sorduğu şey budur - OP'nin gerçekte ne istediğine varsayımsal bir oyun tasarımı uygulamakta yanılıyorsunuz, tasarımının çoğu standarda göre yanlış olup olmadığına bakılmaksızın.
gbjbaanb
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.