Kalıcı çevrimiçi oyunlarda oyuncunun durumunu ne sıklıkla kurtarabilirim?


9

Çevrimiçi oyunlarda, insanlar istedikleri zaman oturum açıp kapatmayı tercih ederler. Genellikle, oyundaki başarıları sunucuya sorunsuz bir şekilde kaydedilir. Bunu başarmak o kadar da zor değil, ama mantıklı ve ölçeklendirilmiş etkili bir şekilde nasıl yapılabileceğini merak ediyorum.

Oyuncunun koordinatlarını kaydetmek ve her gönderdiklerinde durumu belirtmek mantıklı mı? Benim node.js sunucu yanıt engellemeden yapabilirim kolayca ve bir Mongo veritabanı kullanmak istiyorum, ama belki bir saniye kez ve sunucu genelinde durumunda, bir kerede tüm toplama bunu daha uygun değil mi?


Oyun durumunu her 10 saniyede bir kaydediyorum. Bu yeterli olduğunu düşünüyorum, fark edilmeden gidiyor (ve 512Mb RAM olan netbook üzerinde MMORPG sunucumu çalıştırıyorum).
jcora

Yanıtlar:


10

Aklımda World of Warcraft gibi geleneksel bir MMORPG var.

Her oyuncunun ve otonom şeyin her komutundan sonra kaydedin (örn. NPC)

  • Sürekli yedekleme. Sunucu her an aşağı inebilir ve oyunun durumu o ana kadar kaydedilir (veya mümkün olduğunca güncel).
  • Sunucu performansına etkisi; engellemese bile (yani başka bir iş parçacığında), veritabanı başka bir sunucuda olsa bile, aksi takdirde yapmayacağınız işlemektedir. Söylediğiniz gibi engellemiyorsa, başka bir iş parçacığının bunu ele alması gerekir ve bu başka bir şeyle meşgul olabilecek bir iş parçacığıdır.
  • Artırılmış disk G / Ç, böylece risk / arıza oranı artar. Bu, daha düşük ömürleri nedeniyle depolama için SSD'ler kullanıyorsanız özellikle endişe vericidir.
  • Veritabanını başka bir sunucuya yüklerseniz, bant genişliği artar; bu, bant genişliği için ödeme yapıyorsanız ve ayrı bir ağ kartında değilse, o zaman oyuncu trafiğini işlemek için daha iyi kullanılabilecek kaynakları alıyor olabilir.
  • Sunucu bu komutların durumunu kaydetme konusunda daha da ileri giderse ne olur? Yani kaydedilebileceğinden daha fazla komut gelirse, kuyrukta birikirler mi? Bu kuyruk taşar ve hataya neden olur mu? Sıranın yakalanabilmesi için her şeyi durduruyor musunuz?
  • Bana göre bu yaklaşım basit gibi görünse de dikkatle planlanmalı. Örneğin, birbirine dayanan ardışık komutların birlikte kaydedilmesi gerekir; aksi halde komutların ortasında bir arıza meydana gelebilir ve sadece biri kaydedilecek, diğeri kaydedilmeyecektir. İki oyuncunun bir işlem yapıp yapmadığını ve iki komutun diske kaydedilip kaydedilmediğini düşünün: "alıcıya öğenin 1'ini ekle" ve "öğenin 1'ini gönderenden çıkarma". İlk komuttan sonra ancak ikinci komut kaydedilmeden önce bir hata oluşursa, öğe çoğaltmanız olur. (sipariş tersine çevrilirse, kaybolan bir öğeniz vardır)

Her şeyi periyodik olarak kaydet

  • Bir arıza durumunda, sunucu biraz güncelliğini yitirecektir. Umarım günlüklü bir yaklaşım gibi bir şey kullanırsınız, bu yüzden en son anlık görüntü en azından tam ve tutarlı olur ve tüm aktif oyuncular aynı miktarda geri ayarlanır.
  • Kullandığınız veritabanı sistemi, toplu güncelleme için bir optimizasyona sahip olabilir;
  • Bunun yerine ikili bir dosya sistemi seçerseniz, bu yöntem son derece basittir. Yeni bir dosya oluşturun, içine bellek dökün, ucuna yedeklemenin tamamen tamamlandığını gösteren bir işaret atın. Bir yedekleme tamamlandığında, önceki yedeklemeyi silin (veya etmeyin).
  • Yedekleme işleminin, bölünmemesi gereken ardışık komutların ortasına kaydetme gibi diğer bölümün son madde işaret noktasında belirtilenleri de hesaba katması gerekebilir. Tüm veri kümesini kilitlemeyi, diske atmayı ve kilidini açmayı seçebilirsiniz, ancak ne kadar zaman alacağına bağlı olarak, oyunda oldukça ağır bir duraklama veya yavaşlamaya neden olabilir.

Bir karakteri çıkışta kaydetme (başka bir şey kaydetme)

  • Bir oyuncu için en önemli şey, sahip oldukları eşyaları, kazandıkları becerileri, arkadaş listesini vb. İçeren karakterleri. Bir canavarı öldürürlerse ve ganimet önlerinde yerdeyse ve sonra sunucu başarısız olursa, ganimetlerini alma şansına sahip olmamalarında biraz kalbi kırılırlar, ama üstesinden gelirler. Bu yüzden önemli şeyleri saklayın ve küçük şeyleri terlemeyin. Örneğin, NPC'lerin konumlarını kaydetmeyin; sunucu çökerse, geri geldiğinde, olması gereken genel alanda ortaya çıkarlar. İstisna, elbette, herhangi bir nedenden dolayı bir yerde kalmaları gereken "akıllı" NPC'ler içindir. sunucu çöktüğünde oldu.
  • Ayrıca, bir oyuncu bir seferde çok fazla saat boyunca giriş yapmamalıdır (burada "lobiye geri dönmeyi" oturumu kapatmayı düşündüğümü unutmayın). Sonunda bir banyo molası vermeleri ya da yiyecek almaları ya da ebeveynleri / arkadaşları / ne olursa olsun ya da uykuları tarafından kesilmeleri gerekecektir. Bu yüzden, en sert oyuncu için bile 8 saatten fazla gerçekçi bir şekilde oturum açmamalılar. Bir "oyuncu" çok uzun bir süre oturum açarsa, ya birden fazla kişi ya da bir bot olması ve her ikisinin de arzu edilen ya da normal olmaması ihtimali yüksektir.
  • Ayrıca, çıkış işleminiz yukarıda belirtilen ardışık komutlar gibi şeyleri zaten kontrol ediyor olmalıdır. Aslında karakteri zaten dolduruyor olmalı, bu yüzden açıkça diske dökmek için en iyi zaman.

Kapanış düşünceleri

  • Açıkçası son yaklaşımdan yanayım, ama üçü hakkında tarafsız olmaya çalıştım.
  • İlk iki yöntemden hangisinin daha israflı olduğunu söylemek zor. İlk yöntemle, karakter birkaç hareket komutu gönderirse, bunların her biri diske kaydedilir ve üzerine yazılır, açıkça bir tanesine paketlenebildiklerinde. Ancak ikinci yöntemle, popülasyonunuzun yarısının yanında duruyorsanız, son yedekleme işleminden bu yana aynı konumlar olsa bile konumları diske kaydedilir. Üçüncü durumda, birisinin oturum açması ve hemen oturumu kapatması çok olasıdır, ancak çoğu zaman oyuncu hakkında birçok şey değişmiş olacak, böylece savurganlık en az gibi görünecektir.
  • Bunun, arıza durumunda tamamen yedekleme için olduğunu ve bir arızanın kesinlikle en aza indirilmesi gerektiğini unutmayın. Bu istisna durumunu ele almak iyidir, ancak sonunda sunucu başarısız olursa, bazı veriler kaybolacak ve bazı oyuncular üzülecektir. Bu yüzden, yapabileceğiniz her yöntemi, en basit veya en iyi olduğunu düşündüğünüz her şeyi uygulayın ve devam edin.
  • Varsayılan kaydetme olarak buna güvenmeyin; Sunucu uygulamanızda, bağlantıları incelikle kapatan ve her şeyi veritabanına yazan güzel bir kapatma düğmesi yerleştirin. Bunu normal şekilde kullanın.

Son olarak, bu tavsiyeyi mutlak gerçek olarak almayın. Çok oyunculu bir yedekleme sistemi yazmadım. Ben am Bunu düşündüm ve yukarıda düşüncelerimi yazdım neden olan bir online "oyun" üzerinde çalışıyor, ama henüz bu uygulama aşamasına kazanılmış değil. Yani bu gerçek bir deneyim olmadan yazılır, ancak konu hakkında çok fazla okuma ve toplamadan sonra.


4
Kişisel olarak gözlemlediğim kadarıyla ticari MMO'lar bunların üçünün bir kombinasyonunu kullanır. Kayıtlar, kritik olmayan eylemlerin kaçırılmasını önlemek (ve uzun süre oturum açmış olanları cezalandırmamak için) ve her zaman oturumdan çıkmak için, patron öldürme / yağma / ticaret gibi önemli olay ve eylemlerden sonra gerçekleşir. Tek bir yöntem genellikle yeterli değildir. Bu yöntemlerin neredeyse tamamı, bir donanım arızası varsa şeffaf bir şekilde yedeklenen ve geri yüklenen temeldeki bir SQL stili veritabanına dayanır.
NtscCobalt

@NtscCobalt - "SQL tarzı veritabanı" na kadar seninleydim. SQL gerçekten bir gereklilik mi? NoSQL ne olacak?
Mart'ta beatgammit

@tjameson Yorumum NoSQL'e dokunmadan önce yazılmıştı. Sadece kendi biçiminizi yuvarlamamanız gerektiğini söylemeye çalışıyordum ama yine de şemayı önceden bilmeniz gerektiği gibi SQL'i tavsiye ederim (ya da tembel olun ve Entity-Key-Value kullanın) ve tutarlılık daha önemlidir verileri bölme becerisi. Daha fazla bilgi için stackoverflow.com/questions/7339374/… adresine bakın .
NtscCobalt

1

Oyun türüne ve oyuncular ile sunucu arasındaki trafik miktarına bağlı olduğunu düşünüyorum.

Bir MMORPG'de, bilgileri sunucuya her gönderdiklerinde oyuncuların konumunu kaydetmek mantıklı olmaz. Tabii ki, oyuncunun mevcut verileri 'bayat' olduğunda güncelleme daha anlamlı olur. Oyuncunun durumunu yeni bölgeye geçmek, bir patronu yenmek veya bir mağazadan çıkmak gibi önemli olaylarda kurtarmak da yararlı olabilir.

Sırayla oynanan bir oyunda, oyuncunun sırasını her sona erdiğinde ve rakip oyuncunun dönüşünden sonra (sağlık kaybını, büyü efektlerini vb. Kaydet) kesinlikle mantıklı olacaktır.

Yine, cevap tamamen ölçeğe ve sunucunuzun yeteneklerine bağlıdır. Her şey en iyi dengeyi bulmak ve kaliteden ödün vermeden mümkün olduğunca optimize etmekle ilgilidir.


1

Tek endişeniz oturumu kapattıklarında ise, basit bir cevap, oyun dünyasında artık mevcut olmayan koşullar (oturumu kapatma veya bağlantı kesme nedeniyle) ortaya çıktığında konumlarını kaydetmektir.

Bir yan not olsa da, ben sunucu pozisyonuna rapor istemci biraz dikkatli olurdu, ya da en azından bir çeşit sunucu tarafı sağlık kontrolü olmadan. Zaten bunu zaten uyguladıysanız, istemciden doğrudan veri alma konusunda endişelenmenize gerek olmadığından, bu oturumu kapatıp kaydedebilir veya bağlantıyı kesebilirsiniz.


Evet, bu nedenle sunucuya pozisyon ve XP gibi değerler hakkında düzenli güncellemeler gönderme ihtiyacı. Ne kadar uzun süre bırakırsanız, oyuncunun bildirilen deltaları gerçekten indirip indirmediği konusunda daha tartışmalı hale gelir. Bu "check-in" sürelerini kısıtlarsanız izlemek / kontrol etmek çok daha kolaydır.
Mühendis

Uzun süren bir tarayıcı oyununda tam olarak bir oyuncunun oturumu kapattığını söyleme sorunu aslında önemsiz değildir.
Kasım'da Lanbo

Önemsiz olduğunu kabul ediyorum, ancak sadece avatarlarının artık görünmediğine karar vermek için bile olsa, çoğu oyunda şu ya da bu şekilde ele almanız gereken bir sorun. Bu yapıldıktan sonra, bu senaryoya bağlanmak ve son geçerli konumlarını kaydetmek nispeten basit bir konu olmalıdır.
Lunin
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.