どのくらいの頻度で永続的なオンラインゲームでプレーヤーの状態を保存しますか?


9

オンラインゲームでは、ユーザーはいつでもログオンとログオフを好みます。通常、ゲームの実績はサーバーにシームレスに保存されます。それを達成することはそれほど難しいことではありませんが、理にかなった効率的な方法で、どのようにして規模を拡大できるのでしょうか。

プレイヤーの座標と状態を送信するたびに保存することは理にかなっていますか?私のnode.jsサーバーは応答をブロックせずにそれを簡単に行うことができます。Mongoデータベースを使用したいのですが、1秒に1回、サーバー全体のイベントで一度にすべてを収集する方が適切でしょうか。


ゲームの状態を10秒ごとに保存します。私はそれで十分だと思います、それは気付かれません(512MBのRAMを搭載したネットブックでMMORPGサーバーを実行しています)。
jcora

回答:


10

私はWorld of Warcraftのような伝統的なMMORPGを念頭に置いています。

各プレイヤーからのすべてのコマンドと自律的なもの(NPCなど)の後に保存します

  • 常時バックアップ。サーバーはいつでもダウンする可能性があり、ゲームの状態はその瞬間まで(またはとにかくできるだけ最近)保存されます。
  • サーバーのパフォーマンスへの影響。それが非ブロッキング(つまり、別のスレッド上)であっても、データベースが別のサーバー上にある場合でも、他の方法では実行できない処理です。あなたが言うようにそれが非ブロッキングである場合、別のスレッドがそれを処理する必要があり、それは他の何かで占有されている可能性があるスレッドです。
  • ディスクI / Oが増加するため、リスク/失敗率が増加します。寿命が短いため、ストレージにSSDを使用している場合、これは特に懸念事項です。
  • データベースを別のサーバーにオフロードすると、帯域幅が増加します。これは、帯域幅の料金を払っている場合に問題になる可能性があり、別のネットワークカード上にない場合は、プレイヤートラフィックの処理に使用できるリソースを消費しています。
  • サーバーがこれらのコマンドの状態の保存でさらに遅れをとった場合はどうなりますか?つまり、保存できるよりも多くのコマンドが入ってくると、それらはキューに山積みされますか?このキューはオーバーフローしてエラーを引き起こしますか?キューが追いつくことができるようにすべてを停止しますか?
  • このアプローチは簡単に聞こえるかもしれませんが、慎重に計画する必要があるようです。たとえば、互いに依存する連続したコマンドは一緒に保存する必要があります。そうしないと、コマンドの途中で障害が発生し、一方のみが保存され、もう一方は保存されません。2人のプレイヤーがトレードを実行し、2つのコマンドが「アイテムの1つを受信者に追加する」および「アイテムの1つを送信者から減算する」というディスクに保存されているかどうかを検討します。最初のコマンドの後、2番目のコマンドが保存される前に障害が発生した場合、アイテムが重複しています。(順序が逆の場合、失われたアイテムがあります)

すべてを定期的に保存する

  • 障害が発生した場合、サーバーは多少古くなります。うまくいけば、ジャーナル化されたアプローチのようなものを使用するので、最新のスナップショットは少なくとも全体的で一貫性があり、すべてのアクティブなプレーヤーが同じ時間だけ遅れます。
  • どのデータベースシステムを使用する場合でも、バッチ更新が最適化される可能性があります。これは、一度に1つずつ更新するよりも効率的(オーバーヘッドが少ない)です。
  • 代わりにバイナリファイルシステムを選択した場合、この方法は非常に簡単です。新しいファイルを作成し、そこにメモリをダンプし、最後にマーカーがスローされ、バックアップが完全に完了したことを示します。1つのバックアップが完了したら、以前のバックアップを削除します(または削除しません)。
  • バックアッププロセスでは、他のセクションの最後の箇条書きで言及されている、たとえば、分割してはならない連続したコマンドの途中での保存なども考慮する必要があります。データセット全体をロックし、ディスクにダンプしてロックを解除することもできますが、どれだけ時間がかかるかによっては、ゲームでかなりの一時停止やスローダウンが発生する可能性があります。

ログアウト時にキャラクターを保存する(他に何も保存しないでください)

  • プレイヤーにとって最も重要なことは、彼らのキャラクターであり、彼らが持っているアイテム、彼らが獲得したスキル、彼らの友達リストなどを含みます。彼らがモンスターを殺し、戦利品が彼らの前の地面にあり、それからサーバーが失敗した場合、彼らは戦利品を拾う機会がなかったので少し心が痛むでしょうが、彼らはそれを乗り越えるでしょう。だから、重要なものを保存し、小さなものを気にしないでください。たとえば、NPCの位置を保存しないでください。サーバーがダウンした場合、サーバーが復旧すると、サーバーは本来あるべき一般的な領域に出現します。もちろん、例外は、何らかの理由でその場所に留まる必要がある「スマート」NPCです。サーバーがダウンしたときでした
  • さらに、プレーヤーは一度に何時間もログインしないでください(ここでは、ログアウトとして「ロビーに戻る」ことを検討しています)。彼らは最終的にトイレ休憩を取るか、食べ物を手に入れるか、親/友人/何であれ邪魔されたり、睡眠をとったりする必要があります。したがって、最もハードコアなゲーマーであっても、実際には、たとえば8時間以上ノンストップでログオンするべきではありません。「プレーヤー」が非常に長い時間ログオンしている場合は、複数のユーザーまたはボットのいずれかであり、どちらも望ましくない、または通常ではない可能性があります。
  • また、ログアウトプロセスでは、上記の連続したコマンドなどがすでにチェックされているはずです。それは本質的に既にキャラクターをパックしているはずなので、それをディスクにダンプするのは明らかに最高の時です。

終わりに

  • 明らかに私は最後のアプローチに賛成ですが、私は3つすべてについて偏りがないように努めました。
  • 最初の2つの方法のどちらがより無駄であるかを言うのは困難です。最初の方法では、キャラクターが複数の移動コマンドを送信する場合、それらが明確に1つにパッケージ化できる場合、これらはそれぞれディスクに保存されて上書きされます。ただし、2番目の方法では、人口の半分が立っている場合、最後のバックアップ操作以降の位置がまったく同じであっても、その位置はディスクに保存されます。3番目のケースでは、誰かがログオンしてすぐにログオフする可能性が非常に高いですが、ほとんどの場合、プレーヤーに関する多くのものが変更され、無駄が最小限に見えるようになります。
  • これは、障害発生時のバックアップ用であり、障害は最小限に抑える必要があることに注意してください。この例外ケースを処理することは良いことですが、結局、サーバーに障害が発生すると、一部のデータが失われ、一部のプレーヤーが混乱することになります。したがって、できる限りの方法を実装し、最も単純または最良と思われるものを実装して、続行してください。
  • デフォルトの保存としてこれに依存しないでください。サーバーアプリケーションに適切なシャットダウンボタンを配置します。これにより、接続が正常に閉じられ、すべてがデータベースに書き込まれます。通常はご利用ください。

最後に、このアドバイスを絶対的な真実として受け取らないでください。マルチプレイヤーバックアップシステムを作成していません。私オンラインの「ゲーム」取り組んでいるので、これについて考え、上に私の考えを書きましたが、まだこれを実装する段階に達していません。したがって、これは実際の経験なしで書かれていますが、トピックに関する知識をたくさん読んで収集した後です。


4
私が個人的に観察した商業的MMOから、これら3つすべての組み合わせを使用しています。重要なイベントやボスの殺害、略奪、取引などのアクションの後に保存が行われ、重要でないアクションを見逃さないように定期的に(そして長期間ログインしているユーザーを罰しないように)、常にログアウト時に保存されます。通常、1つの方法では不十分です。これらのメソッドのほとんどすべてが、ハードウェアの誤動作が発生した場合に透過的にバックアップおよび復元される、基になるSQLスタイルデータベースに依存しています。
NtscCobalt

@NtscCobalt-「SQLスタイルデータベース」まで一緒にいました。SQLは本当に必要条件ですか?NoSQLはどうですか?
beatgammit 2013年

@tjamesonまあ私のコメントは、NoSQLに触れる前に書かれました。私はあなたがあなた自身のフォーマットを転がすべきではないと言っているだけでした、とにかく私はあなたがスキーマを事前に知っているべきである(または怠惰でEntity-Key-Valueを使用する)そして一貫性がより重要なのでSQLをお勧めしますそのデータを分割する機能。詳細については、stackoverflow.com / questions / 7339374 /…をご覧ください。
NtscCobalt 2013年

1

それは、ゲームの種類、プレイヤーとサーバー間のトラフィック量に依存すると思います。

MMORPGでは、サーバーに情報を送信するたびにプレーヤーの位置を保存しても意味がありません。いわば、プレーヤーの現在のデータが「古くなった」ときに更新する方が理にかなっています。新しい領域への進入、ボスを倒したり、店を出たりするなどの主要なイベントでプレイヤーの状態を保存することも有益かもしれません。

ターンベースのゲームでは、プレイヤーがターンを終了するたびに、また相手のプレイヤーのターンの後に(ヘルスロス、スペルエフェクトなどを保存して)、プレイヤーの状態を保存することは間違いなく理にかなっています。

繰り返しになりますが、答えはサーバーの規模と機能に完全に依存します。それはすべて、最高のバランスを見つけ、品質を犠牲にすることなく可能な限り最適化することです。


1

唯一の懸念がログオフ時である場合、1つの簡単な答えは、(ログオフまたは切断のために)ゲームの世界に存在しなくなった状況が発生したときに位置を保存することです。

ただし、余談ですが、クライアントがサーバーの位置を報告していること、または少なくとも何らかの形でサーバー側の正常性チェックが行われていないことについては、少し警戒します。ただし、これを既に配置している場合は、クライアントから直接データを取得することを心配する必要がないため、ログオフまたは切断時にその位置を保存できます。


ええ、それゆえ、位置やXPのような値でサーバーに定期的な更新を送信する必要があります。あなたがそれを離れる時間が長いほど、プレイヤーが報告されたデルタを実際に積み上げたかどうかに関して、より議論の余地があります。これらの「チェックイン」期間を制限すると、監視/制御がはるかに容易になります。
エンジニア、

長時間実行されているブラウザゲームで、プレーヤーがいつログオフしたかを正確に判断するという問題は、実際には簡単なものではありません。
Lanbo、2011年

些細なことではないことに同意しますが、アバターがいつ表示されなくなるかを判断するだけでも、ほとんどのゲームで何らかの方法で対処する必要があります。それが完了すると、そのシナリオにフックして最後の有効な位置を保存することは比較的簡単な問題になるはずです。
Lunin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.