Bir Oyun İstemcisini Dünya hakkında ne sıklıkta güncelleyebilirim?


10

Socket.io kullanarak , diğer MMORPG'lerinkine benzer bir iletişimim var, mesajlarla sabit bir bağlantı.

Şimdiye kadarki tasarımımda, müşteri her güncelleme çerçevesiyle oyuncunun pozisyonunu ve animasyon karesini gönderiyor. Sunucu bu iletiyi aldığında, tüm istemcilere yayınlar, bu da grafiği buna göre hareket ettirir.

Bunları 'toplamak' ve örneğin saniyenin 1 / 10'unda bir kez yayınlamak daha iyi bir fikir olabilir mi?

Ayrıca, müşteri meydana gelir gelmez çok sayıda farklı mesaj göndermeli (kazanılan, tıklanan) mı yoksa toplanan mesaj mı? İlki daha kolay uygulanacaktı.

Yanıtlar:


16

Bu konuya üst düzey bir tartışmadan yaklaşacağım ve sonra sorularınıza doğru çalışacağım. Açıklamak amacıyla, socket.io kullanarak kişisel bir deneyimim yok, ancak MMORPG'lerle ilgili olarak sorun alanına çok fazla maruz kalıyorum.

Bir MMORPG motorunun ağ mimarisinin tasarımı ve / veya işlevselliği sağlamak için bir orta eşya veya açık kaynaklı proje seçimi, ekibin oyun tasarımı, bütçesi ve teknik uzmanlığından etkilenen daha zor kararlardan biridir. Nihai seçim, diğer mimari kararları (ve bazen de tasarım kararlarını) etkileyecektir.

MMORPG'lerin geliştiricileri olarak, büyük sayıların uyarı ışıklarını ve sirenleri tetiklediği büyük başarı (genellikle katastrofik başarı olarak da bilinir) planlıyoruz. Kırpılan korkunç büyük sayılardan biri N-kare (bundan sonra N ^ 2) olan algoritmalardadır, sorunuzda bana atlanan ilk şey, bir varlığın bilgi yayınlaması için çağrılan tasarım gibi görünmesidir. diğer tüm bağlı varlıklar. Bu bir N ^ 2 sorununun klasik örneğidir.

MMO'lar genellikle N ^ 2 sorunlarını ele almak için soruna birkaç farklı şekilde saldırırlar; bir işletmenin diğer tüm varlıkların bazı alt kümelerinin farkında olduğu, oyuncuları farklı "kırıklara" bölen, oyuncuları "bölgelerdeki bölümlere ayıran ve / veya örnekleyen, çok fazla caydırıcı oyun mekaniğini uygulayan farkındalık sistemleri (durumsal, mekansal, vb.) Birlikte toplanan oyuncular (Asheron Call'un ışınlanma fırtınaları) vb.

Çoğu MMORPG ve birçok FPS motoru, aşağıdakileri içeren çeşitli özellikleri destekleyen oldukça karmaşık ağ oluşturma mimarilerine sahiptir:

  • güvenilir ve güvenilir olmayan iletişim yolları (TCP, güvenilir UDP ve UDP paketlerinin özel uygulamaları)
  • bant genişliği şekillendirme (önceliklendirme, yaşam süreleri, vb.)
  • alan / aktarılabilir veri ve fonksiyon çağrılarının otomatik olarak kopyalanması
  • atomik veri kümeleri (yani birlikte iletilen veriler)
  • ayrı güncellemeler (yani her geçişin önemli olduğu yerlerde)
  • gecikme düzeltmesi
  • müşterinin duyarlı hissetmesini sağlamak için çeşitli hileler

Bunu bulmak Unreal Ağ Dokümantasyon ve Vana Ağ Dokümantasyon çeşitli konularda iyi bir astar sağlar.

Şimdi sorulara yaklaşalım.

Bunları 'toplamak' ve örneğin saniyenin 1 / 10'unda bir kez yayınlamak daha iyi bir fikir olabilir mi?

Burada basit bir evet veya hayır yanıtı vermek zor ... çünkü ölçeğe (gözlemlenen varlık sayısı), güncelleme sıklığına ve güncelleme boyutuna bağlıdır. Örneğin, güncellemelerin boyutu bir yerde bir arabellek patlatabiliyorsa, hepsini toplamak korkunç derecede yanlış olabilir.

MMORPG'ler ve FPS oyunları istemcisi genellikle "normal" olandan çok daha fazla güncelleme çerçevesi için bir güncelleme almasalar bile "doğru" görünen bir şeyi görselleştirecek şekilde tasarlanmıştır. Güvenilmez iletişimi (UDP) kullanırken, boşluğa bir miktar güncellemeyi kaybetmeyi bekleyebilirsiniz, müşteriler bunu güvenilir bir aktarımla kullanılabileceğinden daha sık güncelleme göndererek telafi edebilir.

Socket.io belgelerinin bir el yazısı incelemesinden, güvenilir ve güvenilir olmayan (terminolojisinde geçici) iletişim yollarını desteklediği anlaşılmaktadır.

Buna ilk olarak, güncellemelere hangi sıklıkta ihtiyaç duyulduğunu ele alarak yaklaşırım ...

Bir oyuncu düz bir çizgide sabit bir hızda hareket ediyorsa, gözlemleme istemcileri oynatıcının herhangi bir zamanda nerede olacağı konusunda yüksek doğrulukla tahmin edebileceğinden, daha düşük bir güncelleme frekansı iyidir. Bir oyuncu dar bir daire çizerken veya hızlı yön değişiklikleri yaparken, çok daha sık güncelleme yapılması gerekir. Tersine, bir oyuncu hiç hareket etmiyorsa, hareket güncellemelerini göndermek için hiçbir neden yoktur.

Ne olursa olsun, istemciden sunucuya her kareyi güncelleştirmek için (genellikle) gerekli değildir. Sunucunun kendisi, sahip oldukları her kareye ileti göndermeyi veya geciktirmeyi seçebilir (bkz. Bant genişliği şekillendirme, önceliklendirme ve güncelleme ömrü).

Diğer güncelleme türleri farklı özelliklere sahiptir ... örneğin, bir oyuncu veya yaratık hasar gördüğünde değiştirilen bir "sağlık" alanını düşünün. Bunu uygulamanın bir yolu, gerçekleştiğinde her değişikliği hemen yayınlamaktır, ancak değer bir çerçevede veya ardışık çerçevelerde birden çok kez değiştirilirse işleme ve bant genişliğini boşa harcar (bant genişliği şekillendirme uygulayan ağ mimarileri, güncellemeleri birleştirerek bu sorunu çözer. yalnızca en sonuncusu, kullanılabilir bant genişliğine sahip olduğunda gözlemleyen bir istemciye gönderilir).

Müşteri, meydana gelir gelmez çok sayıda farklı mesaj göndermeli mi (elde edilen harcama, tıklanan) mı yoksa toplanan mesaj mı?

Yine, burada basit bir evet veya hayır cevabı işe yaramayacaktır. Toplananla tam olarak ne demek istediğinize bağlı olarak ... her ikisi de farklı koşullar altında doğru olabilir ve ağ katmanının uygulanmasına da bağlı olabilir.

Tek bir mesaj olarak gönderilecek belirli bir varlık için mesaj toplamak (uygulamaya bağlı olarak) bir mesaj göndermek için bant genişliğini ek yükü azaltabilir (maliyetlerinizi düşürür) (dizelerle iletilen alan / değer eşlemeleri gibi uygulamaya bağlı olarak) bant genişliğini artırabilir daha basit bir mesaj türüne kıyasla gereksinimler.

Socket.io dokümantasyonunu gözden geçirdiğimde, mesaj ek yükünün spektrumun üst ucunda olduğu görülüyor ve bu da çok sayıda tekli güncellemenin aksine toplu mesaj olarak gönderilecek güncellemeleri toplamayı tercih ediyor.

Çoğaltmayı düşündüğünüz tüm güncellemeleri gözden geçirmenizi öneririm, örneğin çoğu MMORPG ve FPS, farkında oldukları bir nesne için durum değişikliğine neden olmadıkça X olaylarına tıklanan oynatıcıyı istemcilere gözlemlemeye göndermez. .


3
+1 Harika cevap. Ayrıca basit başlangıç ​​ve oradan optimize öneririz. Spam iletiler, elbette, çılgınca gidin ve bant genişliğinizin patlamaya başladığını görün. Bu nedenle aşamalı stres testi yaptırmak iyidir. Mümkün olan en saf yaklaşımı uygularsınız ve bazı testler yaparsınız; bazı optimizasyonlar yapıyorsunuz; tekrar stres testi, daha da optimize, durulayın, tekrarlayın. İlk gün bir optimizasyon uygulamak kesinlikle önemsiz ise, devam edin; ancak en önemsiz optimizasyonların bile daha sonra bir üretim ortamında reddedilebilecek varsayımlar taşıyabileceğini unutmayın.
Mühendis

5

İşte gerçek dünya örneği: RuneScape ~ 0.6 saniyede bir "keneler". Burada okuyabilirsiniz . Sanırım senaryolarında şeyleri milisaniye yerine kenelerde zamanlamaları ve gecikmeleri belirledikleri için perspektiflerinden basitleştirdiğini hayal ediyorum. Ve elbette, böyle büyük / yavaş bir kene oranı ile, yavaş bağlantıları olan kullanıcılar diğer oyunculara kıyasla büyük bir dezavantajda değildir.


0

Çalışmanın bir yolu, gerçek veri değişikliklerini bu değişikliklerin yayınlanmasından ayırmaktır. Bir nesne değiştiğinde, değişikliği yapın ve 'kirli' bir bayrak ayarlayın ve herhangi bir değişikliği yayınlama zamanı geldiğinde, yalnızca işaretli nesneler için veri gönderin ve bayrağı temizleyin. Güncellemeniz yalnızca yayın sırasında durumu gönderdiğinden, birden çok kez değiştirilen değerler burada otomatik olarak birleştirilir. Ayrıca yalnızca değişenleri yayınlamak için alt nesneleri veya tek tek özellikleri işaretleyebilirsiniz.

Oh, ve genellikle animasyon karelerini sunucuya veya diğer istemcilere göndermezdiniz. Kesin animasyon durumu genellikle bir sunum detayı olarak kabul edilir ve çözmek için her istemciye bırakılır ve bunun yerine her müşterinin şu anda hangi animasyonun oynatıldığını bildiğinden emin olursunuz.


Yapmaz mıydım? Peki ya pozlar ya da bir şey, tüm müşterilerin aynı gördüklerinden emin olmam gerekir?
Lanbo

Her müşterinin aynı şeyi görmesini sağlamak oldukça pratik değildir, çünkü bilgi seyahat etmek zaman alır, farklı müşteriler farklı ağ gecikmelerine sahiptir, farklı hızlarda oluştururlar, vb. Bu nedenle herkesin aynı çerçeveyi aynı anda göstermesini sağlamak genellikle nafile çaba. Bunun yerine, aynı animasyonu kabaca aynı anda başlattıklarından emin olabilirsiniz ve bu yeterince iyidir.
Kylotan
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.