Hem istemci hem de sunucuda bir fizik simülasyonu mu çalıştırıyorsunuz?


13

Oyunlarda istemci / sunucu ağ mimarisi hakkında bilgi edinmek için çok oyunculu bir asteroit klonu uyguluyorum. Onların istemci / sunucu teknoloji GafferOnGames ve Valve'ın yayınlarını okumak için zaman geçirdim. İki kavramla ilgili sorun yaşıyorum.

  1. Şu anda box2d ile fiziği simüle eden ve dünyanın durumunu saniyede 20 kez istemcilere gönderen yetkili bir oyun sunucum var. Her müşteri, sprite hareketini yumuşatmak için son birkaç anlık görüntüyü takip eder ve iki durum arasında geçiş yapar. Ancak o kadar da düzgün değil. Bir süre pürüzsüz olabilir, sonra biraz sarsıntılı, daha sonra pürüzsüz hale gelebilir, vb. Hem TCP hem de UDP'yi denedim, her ikisi de yaklaşık aynı. Sorunumun ne olabileceği hakkında bir fikrin var mı? (Not: Bunu önce tek oyuncu için uyguladım ve fizik dünyasını saniyede sadece 20 kez güncellediğinde sprite hareketi 60 fps'de mükemmel bir şekilde pürüzsüz).

  2. İlk sorunu çözmek için, müşterinin bir box2d simülasyonu da çalıştırması ve sadece spritelarının konumlarını eşleşmediğinde sunucu anlık görüntülerine uyacak şekilde güncellemesi gerektiğini düşündüm. Tek oyunculu uygulamam sorunsuz olduğu için bunun daha pürüzsüz olabileceğini düşündüm. Bu iyi bir fikir mi?

    Yukarıdaki sorunu çözmese bile, müşteri tarafı tahmini için gerekli mi? Örneğin, bir oyuncu gemilerini hareket ettirmeye çalışırsa, fizik simülasyonu olmayan bir asteroit, duvar veya düşman gemisine çarpıp çarpmadığını nasıl anlayacaklar? Gemilerinin, nesneden vurduklarını söyleyen bir anlık görüntü almadan önce çarpışmaları gereken nesneden geçtiği anlaşılıyor.

Teşekkürler!

Yanıtlar:


10

Simülasyonu hem istemcilerde hem de sunucuda kesinlikle çalıştırın. Başka herhangi bir şeyin çok uzun gecikmesi vardır. Nesneleri aynı sırada ekleyerek, sabit bir zaman adımı kullanarak ve işaretçi karşılaştırmasını önleyerek simülasyonların eşleştiğinden emin olmalısınız. Bunu Box2D ile denemedim ancak bir fizik simülasyonundaki tüm makinelerde aynı davranışı elde etmek genellikle mümkündür. Tüm matematik genellikle IEEE 754 binary32 değişkenlerine dayanır ve davranışları, +-*/birkaçını adlandırmak gibi işlemler için kesinlikle tanımlanır . Dikkatli olmalısın sin,cosçalışma zamanları arasında farklılık gösterebildikleri için (bu, özellikle birden çok platform için geliştirilirken önemlidir). Ayrıca derleyicinizde şamandıra optimizasyonları için katı bir ayar kullandığınızdan emin olun. Nesnelerin durumunu düzenli olarak sunucudan göndererek nesneleri eşitleyebilirsiniz. Gereksiz kekemeliği önlemek için fark bir eşik değerden daha büyük değilse güncelleme yapmayın.

Akla gelen bir konu, yeni nesnelerin oluşturulması ve bunun müşteriler arasındaki simülasyonu nasıl değiştireceği. Bunu düzeltmenin bir yolu, sunucunun tüm nesneleri oluşturmasına izin vermektir. Geçerli zaman adımı ise t, sunucu eklenecek nesneyi zamanlayacaktır t+d. Böylece, eklenecek nesneler ve ne zaman eklenecekleri ile yeni bir nesne listesi tüm istemcilerde tutulabilir ve sunucu tarafından önceden güncellenebilir. Eğer dyeterince büyük olduğu, farklı sonuçların riskini en aza indirmek. Farkı gerçekten kaldıramazsanız, istemciyi o zaman adımını simüle etmeden önce belirli bir zaman adımı için yeni nesneler hakkında bilgi beklemeye zorlayabilirsiniz.


Yanıtınız için teşekkürler. Box2d'nin farklı CPU'larda aynı sonuçları üreteceğini garanti etmiyorum, bu da bir masaüstü oyunu yazdığımız için bizim için senaryo olacak. Farklılıkların yetkili bir sunucudan gelen periyodik güncellemelerle dakikalar içinde ve kolayca düzeltilebileceğini umuyorum, ama hiç denemedim.
Venesectrix

Erin Catto, birden fazla Box2D dünyasının tüm durumunu senkronize tutmaya çalışmanın kaybedilen bir savaş olduğunu düşünüyor ( box2d.org/forum/viewtopic.php?f=3&t=8462 )
Pavel

İfadesi "binary32 yüzer [..] davranış kesinlikle gibi işlemler için tanımlanan IEEE 754 +-*/" tamamen yanlıştır. IEEE-754'teki tüm bu işlemler uygulamaya bağlı olarak değişebilir. Daha fazla bilgi için buraya ve buraya bakın .
BlueRaja - Danny Pflughoeft

1
Hayır. Tamamen doğrudur. Bağlantınızın açıkladığı sorun, x87 fpu'nun farklı modları ve transandantal uygulamaları ile ilgilidir. IEEE 754 binary32 , temel işlemler için kesin olarak tanımlanmıştır. Standardı takip etmek için doğru modları ayarlamak ve doğru talimatları kullanmak size kalmıştır. Sadece SSE talimatlarını kullanmak, x87 fpu değil çok yardımcı olur.
rasmus

4

Muhtemelen o kadar iyi görünmüyor çünkü aralarında enterpolasyon yapmak, her zaman enterpolasyon için bir sonraki veri kümesine sahip olmaya dayanıyor. Bu, kısa bir gecikme başlangıcı varsa, her şeyi yakalamak için beklemek zorunda olduğu anlamına gelir.

Orada GameDev eski bir makale son ettiğimiz veriler vardı noktadan sonra bir nesnenin konumunu tahmin etmek kübik spline kullanmayla ilgili. Daha sonra yaptığınız şey bu konumu kullanmak ve yeni konumunu hesaba katmak için yeni veriler aldığınızda spline'ı ayarlamaktır. Muhtemelen ikinci bir fizik simülasyonu çalıştırmaktan çok daha ucuzdur ve bu, kime güvendiğinize karar vermek zorunda olmamanız gerektiği anlamına gelir, çünkü istemciyi ilerlerken telafi ederek açıkça uyguladınız. :)


Durum böyle olabilir. Ne yapmaya çalışıyorum ben sunucudan 3 anlık görüntüleri alıncaya kadar gecikme olduğunu. Bu noktada atış 1'den atış 2'ye geçiyorum. Sonra atış 2'den atış 3'e. Herhangi bir noktada bir paketi kaçırırsam, eğer mantıklıysa, 1'den 2 yerine 1'den 3'e geçebilirim. Yine de bunu doğru bir şekilde uygulamıyor olabilirim. Makaleye bağlantı için teşekkürler!
Venesectrix

1

Kendime benzer şeyler yaptım ve Box2D'yi sadece müşteriler üzerinde çalıştırdım. Yaptığım yol, istemcinin kendi simülasyonunu hemen hemen kendi başına çalıştırmasına izin vermekti, her bir senkronizasyon paketindeki mevcut hızı (ve dönüşü) sunucuya gönderiyordu. Sunucu daha sonra bu bilgileri, yeni alınan hızları çoğaltılmış varlıklara ayarlayan diğer oyunculara gönderir. Müşteriler arasında belirgin bir fark olmadan çok pürüzsüzdü.

Tabii ki, buradaki sorun varlıklar üzerinde merkezi bir kontrol olmaması, ancak bunun fizikte sunucu tarafı simülasyonu yaparak da sunucu tarafında yapılabileceğini düşünüyorum.


Giriş için teşekkürler. Hile yapmayı önlemek için merkezi kontrole ihtiyacımız olacak, bu nedenle sunucunun en azından müşterilerin ne yaptıklarını söylediklerinin mümkün olup olmadığını bilmek için bir simülasyon çalıştırması gerekiyor.
Venesectrix

1

Ben şahsen simülasyonları sadece sunucuda çalıştırmayı ve ilgili nesnelerin meydana geldiklerinde doğrusal / açısal hızlar / ivmelenmelerde herhangi bir değişiklik yayınlamasını tercih ederim. Belirli bir nesne, herhangi bir nedenle, fiziksel özelliklerinden herhangi birini (yukarıda belirtilen hızlar ve ivmeler gibi) değiştirdiğinde, bu özel değişiklik sunucudan istemciye gönderilir ve istemci, nesnenin verileri buna göre.

Mevcut uygulamanıza göre avantajı, müşteri interpolasyonlarının gerekliliğini ortadan kaldırması ve nesneler üzerinde çok sadık bir davranış üretmesidir. Sorun, bu yöntemin gecikmelere karşı oldukça savunmasız olmasıdır, bu da oyuncular coğrafi olarak birbirlerinden çok uzakta olduklarında çok büyük bir sorun haline gelir.

Soru 1'e gelince, sorunun gecikme üzerinde dalgalanmalar olacağını söylüyorum, çünkü anlık görüntünün her alımı arasında tam olarak mükemmel bir 20 saniye ara olacağına dair kesin bir garanti yoktur. Göstereyim (milisaniye cinsinden ölçülen zamanı "t" yaparak):

1) Oyunun başlamasından bu yana t = 20'de, müşteri bir anlık görüntü aldı ve enterpolasyonu başarılı ve sorunsuz bir şekilde yaptı.

2) t = 40 değerinde, sunucu ve istemci arasında bir gecikme vardı ve anlık görüntü yalnızca gerçekte t = 41 değerine ulaştı.

3) t = 60'da, sunucu başka bir anlık görüntü gönderdi, ancak simülasyonun bir saniyesi gecikme nedeniyle istemcinin israfına uğradı. Anlık görüntü t = 60 değerine ulaşırsa, istemci 40 ve 60 örneklerinin enterpolasyonunu yapmayacak, aslında 41 ile 60 arasındaki örneklerden farklı bir davranış oluşturacaktır. Üzerindeki bu yanlışlık, nihai "sarsıntı" nın nedeni olabilir.

Soru 2'ye gelince, her bir nesnenin, nesnelerin konumunu bildiren her bir çerçeveye paket göndermek zorunda kalmadan, her bir nesnenin gerçekten istemci-sunucu senkronize olup olmadığını etkin bir şekilde izleyecek bir şey uygularsanız, fikriniz işe yarayabilir. Ayrık aralıklarla yapsanız bile, yalnızca 1. sorunun aynı sorunu üzerinde çalışmayacak, aynı zamanda çok büyük miktarlarda veri aktarmaya da sahip olacaksınız (bu kötü bir şeydir).


İlk paragrafınızda söylediklerinizi takip ettiğimden emin değilim. Simülasyon yalnızca sunucuda çalışıyorsa ve yalnızca hız / hızlanma değişikliklerini yayınlıyorsanız, istemci spriteların nerede çizileceğini nasıl bilebilir? İstemcilerin nesneleri düzgün bir şekilde çizebilmek için alınan hız / ivmeye göre simüle etmesi gerekir. Tam olarak beklediğimden farklı aralıklarla anlık görüntü alma konusunda haklı olabileceğinizi düşünüyorum. Bununla nasıl başa çıkılacağı hakkında bir fikrin var mı?
Venesectrix

İstemciler nesnelerin başlangıç ​​ve geçerli konumlarını, hızlarını ve ivmelenmelerini bilir ve nesnelerin (sunucudan bağımsız olarak) olduğunu düşündükleri konumu güncelleyecektir . Sunucu, istemcilerdeki bu özellikleri mesajlar yoluyla değiştirecek, çünkü fizik ve çarpışma algılamasını yapan sunucu (er ya da geç verilen nesnenin hızını / ivmesini ve yönünü değiştirmek zorunda)
UBSophung
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.