MMO’da sunucu ile düşük trafik istemcisi senkronizasyonu


22

Oyuncunun uzay gemisi üzerinde ok tuşları ile kontrol ettiği ve diğer oyuncularla işbirliği yaptığı uzayda uçtuğu MMO'yu uyguluyorum.

Oyuncunun gemisini roketten veya başka bir şeyden atlayabilmesi için uygulamak istiyorum, bu yüzden sunucu kullanımıyla aynı dünya simülasyon algoritmasını kullanarak, tüm oyun durumunu müşteri tarafında tahmin etmeye çalışıyorum. Bu oyun dünyası C # ile yazılmıştır ve doğrudan müşteride (Unity3D'de yazılmıştır) ve CLR ile C ++ sunucusunda (Linux altında) çağrılacaktır. UDP ile bağlantı.

Sorun, örneğin, tek bir haritadaki 1000 oyuncuyu nasıl koruyacağınızdır (diğer tüm oyun nesneleri, çeteler hariç): Diyelim ki:

  • Sunucuyu istemcilerle saniyede 50 kez senkronize et
  • Her müşteri durumuna sadece görebildiği oyun alanlarının (ve oyuncuların) (bazı yarıçapların içinde) gönderilmesi
  • görüş açısı dahilindeki her oyuncuya 100 nesne göndermesi gerekir
  • Oyun nesnesi başına ortalama 50 bayt göndermelidir (kimliği, x, y kodları, döndürme, durum ...)

bu nedenle, bu tür ağ bant genişliğine sahip olması gerekecektir: 1000 (müşteri) * 50 (saniyede bir kez) * 100 (her oyuncuya gönderilecek nesneler) * 50 (nesne başına bayt) = saniyede 250 000 000 bayt! Bu imkansız!

Bu değeri bir şekilde azaltmak mümkün mü? Örneğin, müşterilerin oyun dünyalarını tam olarak taklit etmelerine izin verin (uzun bir süre için) ve onlara sadece diğer istemcilerin girişlerini gönderin ve oyun dünyalarını senkronize edin. .

Her neyse, böyle oyunlar ortak şekilde nasıl programlanır? Teşekkür ederim.


1
Nesneler hakkında sadece mantıksal bilgi gönderiyorum (dünyanın konumu, şu anki durumu (bir bayt) ve benzeri) - grafik yok.
Slav

1
@Slav: Güzel! Bütün bu kaymalar bana ASM programlama günlerimi hatırlatıyor.
Randolf Richardson

1
Neden "bugün günler" değil? :) AS3, Java, Lua, C # üzerine yazdığımda ve performansım çok düşükse C ++ 'ı özlüyorum ve ASM'yi hatırlıyorum.
Slav,

1
@Slav: Heheh, son zamanlarda çok fazla ASM yapmadım. Benim için çoğu şey bugünlerde Java ve Perl'de (çoğunlukla mod_perl2), ama ben de bu dillerin tadını çıkarıyorum.
Randolf Richardson

2
@Slav, şöyle yazmışsınız: "AS3, Java, Lua, C # üzerine yazdığım ve performansım çok düşükse C ++ 'ı özlüyorum ve ASM'yi hatırlıyorum". Lua ve C # 'yı düzgün kullanmayı öğrenmelisin, belki performansı daha az berbat bulursun. Ayrıca, (iddia edilen) en hızlı komut dosyası dili hakkında şikayet etmek en iyi tekilde var ... Bu gerçek zamanlı insan genomu analizi ile ilgili bir oyun mu?
Raine

Yanıtlar:


20

Saniyede yalnızca 30 güncellemeye (veya daha az belki 10 veya 20) ihtiyacınız var. istemci tarafındaki hareketli nesnelerin pozisyonlarını enterpolasyon yapar. Genelde yalnızca GERÇEK gerek duyulduğunda veri göndermelisiniz. WoW'da, aynı gruptaki oyunculardan bir grupta olduğunuz oyunculardan daha fazla güncelleme alabilirsiniz. Ayrıca, başka bir oyuncu senden uzaktaysa, saniyede saniyede o kadar fazla güncelleme almazsın.

Ardından, her oyuncuya bağlandığında yalnızca bir tam görüntü gönderir. Bundan sonra sadece oyun nesnelerinin değişikliklerini gönder. Herhangi bir değişiklik olmadıysa göndermeyin.

Ardından, BitVectors'ı yoğun şekilde kullanın, ancak gereksiz veri miktarını azaltmak için onları çağırabilirsiniz! Örnek: Yalnızca bir bayt kullanarak (0 - 1 veya -1 - 1 aralığında) bir float yazmayı da deneyebilirsiniz, böylece yalnızca 256 veya 128 farklı değeriniz olur. Ancak oyuncu enterpolasyonlar sayesinde sarsıntılı hareketler farketmeyecek.

Verileri nasıl sıkıştıracağınıza ilişkin LidgrenLibrary örneğine bakınız: http://code.google.com/p/lidgren-network-gen3/wiki/Optimization

Sonraki: Oyuncular hareket ettikçe görüş yarıçapını azaltmaya çalışın ve o zaman yalnızca önemli bilgileri iletin. Sonra durduklarında tekrar görünüm yarıçaplarını arttırın. "Menzilli" olan nesnelerin aranmasını azaltmak için uzamsal bir karma sistemi veya bir bsp ağacı kullanabilirsiniz. Bu konu için iyi bir okuma: http://en.wikipedia.org/wiki/Collision_detection

Ayrıca veriyi SİZİN KENDİNİZİ yalnızca veri yapısı ve verilerdeki zamansal tutarlılık hakkında bilmek (bundan yararlanılabilir ve yararlanılmalıdır) bilir. Bzip2, Deflate, ne olursa olsun, gibi genel bir algoritma kullanılmalıdır, ancak yalnızca sıkıştırmanın son aşaması olarak kullanılmalıdır!

Ayrıca, oyun kritik olmayan bilgiler için, ek P2P teknikleri de kullanabilirsiniz. Örnek: Bir oyuncu "merhaba" animasyonunu oynatır. (Sadece grafiksel bir etki) Oyuncu bu bilgiyi sunucuya gönderir, fakat sunucu bilgiyi diğer oyunculara aktarmaz. Bunun yerine bu kritik olmayan etki oyuncu tarafından menzil içindeki diğer istemcilere gönderilir.

EDIT (yorum nedeniyle):

Her oyuncuya saniye başına ortalama bit sayısını azaltmak için ek yöntemler:

  1. "Nesne değişmedi" gönderdiğinizi yazdınız. Bunu yapmak için hiçbir sebep yok. Paket kaybı konusunda endişeleniyorsanız (ve bu nedenle simülasyonunuzu senkronize etmeden çıkarmak) aşağıdakileri göz önünde bulundurun: Her bir sabit zaman diliminde (ör. 100, 200, 300, 400 ...) simülasyon durumunu özetleyin ve sunucuya gönderin . Sunucu tüm verinin tam bir görüntüsünü onaylar veya gönderir.

  2. Roket ve hatta oyuncular gibi şeyler için simülasyonu daha gerçekçi hale getirmek amacıyla sadece enterpolasyonu değil, ekstrapolasyonu da kullanabilirsiniz. Örnek 'Roket': "Şimdi x konumunda mı?" Gibi mesajlarla güncellemek yerine, sadece aşağıdakileri içeren bir mesaj gönderin: "Roket Yumurtlandı: pozisyon (vektör), Zaman (simülasyon adımının roketin doğduğu yer), hız ( vektör)". Böylece dönüşü dahil etmeniz gerekmiyor, çünkü uç daima "hız" yönünde olacaktır.

  3. Birden çok komutu tek bir mesajda birleştirin ve udp başlığı mesajın kendisinden daha büyük olacağından, asla 16-20 bayttan daha küçük mesajlar göndermeyin. Ayrıca protokolünüzün MTU'sundan daha büyük paketler göndermeyin, çünkü parçalanma iletim hızını yavaşlatır.


Bazı nesneleri diğerlerinden daha sık güncellemek, P2P kullanmak, kayan nokta doğruluğunu düşürmek, sadece değişiklik göndermek (benim için önemsiz olmayan, çünkü nesneleri periyodik olarak senkronize etmeyi planladım ama "nesne değişmedi") iyi bir fikir. çok). Tüm bu değişikliklerle birlikte tüm resim daha gerçekçi görünüyor!
Slav

1
"Nesne değişmedi" türü bildirimleri göndermek, oyuncular yoğun zamanlardayken oyunun nasıl performans gösterdiğini görmek istediğiniz test amaçlı, ağın yanı sıra işlemeye yönelik taleplerde bulunma potansiyeline sahip olabilir; Bundan daha iyi çözümler var (gerçek bir oyun içi karakter kontrol eden bağımsız bir arka plan yaratma, daha sonra bu deamonu farklı makinelerden defalarca çalıştırma gibi).
Randolf Richardson

5

İşte iki yaklaşım:

Birincisi:
Deterministik fiziğe geçin, oyuncu komutlarını gönderin, ai eylemleri, görüş alan nesneler ve müşterilere müşteri tarafında ne tespit edilemezse. Bu, komutları içermemeli, zaman içerisinde belirli bir noktaya kadar hiçbir şeyin gönderilip alınan komutların geçerli olmadığını gösteren bir onay içermelidir.

Müşteri iki veya üç eşzamanlı simülasyon çalıştırmalıdır.
1: Bir sonraki adım için veri eksik olduğunda durur.
2: Tahmin verilerini kullanmaya devam edin ve oluşturma için kullanılan durumu sağlayın. 3: Ne zaman 1 numara durduğunda, bu simülasyon 1 numara olmayan halini kopyalar, o andaki zamanı yakalar ve 2 numara alır, sonra bırakılır.

Eğer yeteri kadar hızlıysa, no 2 ile no 3 arasındaki farkı bırakabilir ve eski verileri hemen bırakabilirsiniz.

İkincisi:
Deterministik fiziği kullanmayın, yukarıdakiyle aynı yapın, ancak birkaç saniyede bir "tam kare" gönderin. Kolayca tamamen mermi gibi geçici şeyler aktarma dışında bırakabilirsiniz.

Her iki durumda da, müşterinin ölmekte olan birisini tahmin etmesi konusunda temkinli olmak isteyebilirsiniz, bir rakibinin patlamamasını görmek aptalca bir durumdur.

Ve matematik yapmak için +1, çok fazla insan basit kaynak kullanımı tahminlerini yapamıyor.


2
“Deterministik fizik”, kayan nokta değerlerini veya farklı simülasyon adımlarını kullanamayacağım anlamına mı geliyor? Örneğin, roket istemcideki bazı düşman taretinden geçecekse ancak sunucuya (bazı kayan nokta yanlışlıkları nedeniyle) çarpacaksa, oyuncunun bir sonraki gelen sunucunun senkronizasyon paketine kadar bu taretle savaşmaya devam etmesine neden olacaksa, kritik zaman uyumsuzluğunun olabileceğini merak ediyorum. (birkaç saniye).
Slav

3
Tamsayılar ve sabit zaman adımı anlamına gelir. Teorik olarak, hareket etmek için kayan noktalarla alay edebilirsiniz, ancak tamsayıları kullanmak daha kolaydır. Eksik füze örneğiyle ilgili bir noktanız var; deterministik olmayan fizik kullanıyorsanız, sunucunun ölümü tam olarak ele alması ve ölüm / imha vakalarını hızlı bir şekilde iletmesi en iyisidir.
aaaaaaaaaaaa 18:11

5

İlk önce birkaç soru.

'Roket veya başka bir şey' akıllı mı yoksa dilsiz mi? Aptallarsa, ihtiyacınız olan tek şey ateşin zaman damgası, orijini ve vektörünü yollarını simüle etmek. Eğer akıllılarsa ne kadar akıllılar? Ateş sırasında vuracaklarını veya özleyeceklerini hesaplayabilir misiniz? Öyleyse istemcideki yolun tamamını simüle edebilirsiniz. ("T13'te füze gemiye saldıracak, çünkü oyun kaçış atışını kaybetti / atıcı kritik bir vuruş yaptı.")

Genel olarak, bunun için hiçbir sebep yok: A) 50Hz'lik bir saat hızına sahip, (Çoğu atıcı 15-20 ve MMO'lar bundan daha az kurtulur.) B) her kareye tam durum gönderir. (Bir füzenin uzaydaki rotasyonu hiç önemli mi? Yoksa sadece 'ön'ün' seyahat ettiği vektöre yönelik olduğunu varsayabilir misin?)

Tahmini ve enterpolasyonla zaman geçirin ve bant genişliğinizi düşürün Üzerinde çalıştığım bir projenin güncelleme oranı 10Hz ve bence 14 baytlık bir nesne durumu temsil edildi. (Yapabildiğiniz her şeyi sıkıştırın! X düzlemi etrafındaki dönüşü tanımlamak için 6 bit kullandığımızı ve o düzlemin altındaki / üstündeki bir eğim için 6 bit daha kullandığımızı düşünüyorum, gerçek bir dönme matrisi / kuaterniyon göndermekten ayırt edilemez görünüyordu.)

Yapabileceğiniz başka bir şey, nesneleri önceliklendirmektir. Göster, belki ilgili sette 100 nesne var, fakat sunucudaki görüşlerini biliyor musunuz? Eğer onun görüşüne göre bir şey yoksa, güncelleme sıklığını büyüklük sırasına göre düşürebilir misiniz?

Genel fikir müşteriye mükemmel bir simülasyon yapmak değil, bu imkansız, fikir oyuncuların mükemmel bir simülasyon olmadığını farketmeyeceği eğlenceli bir oyun yapmak.

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.