39


17

現代の複雑なゲームでの達成システムの実装

最近作成された多くのゲームには、特定のタスクを達成したプレイヤー/ユーザーに報酬を与える独自の達成システムが付属しています。 ここでのStackoverflowのバッジシステムはまったく同じです。

しかし、いくつかの問題があり、それに対して私は良い解決策を見つけることができませんでした。

アチーブメントシステムは常に特定のイベントに注意する必要があります。たとえば、戦闘で20〜30のアチーブメントを提供するゲームを考えてください。 サーバーはこれらのイベントを確認する必要があります(たとえば、プレイヤーがこの戦闘で対戦相手の_x_攻撃を回避したか、プレイヤーが_x_マイル歩いた)すべての時間

  • サーバーは、この大量の操作を、 遅くなり、おそらくクラッシュしますか?

アチーブメントシステムには通常、ゲームのコアエンジンでのみ使用されるデータが必要であり、それらの厄介なアチーブメントがなければ、そこから必要とされることはありません(たとえば、各戦闘中にプレイヤーがジャンプした頻度、 「この情報をすべてデータベースに保存したくない。)。 つまり、場合によっては、アチーブメントを追加する唯一の方法は、現在の状態をチェックするコードをゲームコアに追加することです。これは通常、非常に悪い考えです。

  • 達成システムは、ゲームのコアとどのように相互作用しますか 後で不要な情報を保持していますか? (上記の例を参照)

  • ゲームのコアからどのように分離されていますか?

私の例は「無害」に思えるかもしれませんが、たとえば、_World of Warcraft_で現在利用可能な1000以上の実績と、同時に多数のオンラインプレイヤーを考えてみてください。

4 Answer


24


アチーブメントシステムは、実際には単なるロギングの形式です。 このようなシステムの場合、http://en.wikipedia.org/wiki/Publish/subscribe [publish / subscribe]が適切なアプローチです。 この場合、プレーヤーは自分自身に関する情報を公開し、関心のあるソフトウェアコンポーネント(個々の成果を処理する)がサブスクライブできます。 これにより、コアゲームロジックに影響を与えることなく、特別なログコードでパブリック値を監視できます。

「プレーヤーが歩いたxマイル」の例を見てみましょう。 歩く距離をプレーヤーオブジェクトのフィールドとして実装します。これは増分する単純な値であり、時間とともにスペースを増やす必要がないためです。 10マイル歩いたプレイヤーに報いるアチーブメントは、そのフィールドのサブスクライバーになります。 多くのプレーヤーがいる場合、この値を1つ以上の中間ブローカーレベルと集約することは理にかなっています。 たとえば、ゲームに100万人のプレイヤーが存在する場合、1000人のブローカーで値を集計し、それぞれが1000人の個々のプレイヤーを追跡することになります。 その後、アチーブメントは、すべてのプレーヤーに直接ではなく、これらのブローカーにサブスクライブします。 もちろん、最適な階層とサブスクライバーの数は実装固有です。

戦闘の例の場合、プレイヤーはまったく同じ方法で最後の戦闘の詳細を公開できます。 戦闘でのジャンプを監視するアチーブメントは、この情報を購読し、ジャンプの数を確認します。 履歴状態は必要ないため、これも時間とともに増加しません。 繰り返しますが、コアコードを変更する必要はありません。一部の値にアクセスできる必要があるだけです。

また、ほとんどの報酬は瞬間的なものである必要はありません。 これにより、トラフィックの管理に多少の余裕ができます。 前の例では、プレーヤーが合計1マイル歩くまで、または最後の更新から1日が経過するまで(それまで内部的にインクリメントされます)、ブローカーの公開された移動距離を更新しません。 これは実際には単なるキャッシュの形式です。正確なパラメーターは問題によって異なります。


4


ビデオゲームエミュレータなどのソースにアクセスできない場合でも、これを行うことができます。 たとえば、表示されたスコアを見つけるための簡単なメモリスキャンツールを作成できます。 達成システムは、フレームごとにそのメモリ位置をポーリングし、現在の「スコア」または最高スコアより高いものを確認するのと同じくらい簡単です。 ビデオゲームエミュレータの素晴らしい点は、メモリの場所が決定的であることです(オペレーティングシステムはありません)。


3


通常のゲームでこれを行うには2つの方法があります。

  1. オフラインゲーム:pub / subほど複雑なものはありません-それは巨大です やり過ぎです。 代わりに、大きなマップ/辞書を使用し、「イベント」という名前のログを記録します。 次に、Xフレームごと、またはY秒ごと(または、通常、「何かが死ぬたびに、レベルの終わりに1倍」)、アチーブメント全体で反復し、クイックチェックを行います。 デザイナーが新しいイベントをログに記録したい場合、プログラマーがそれを記録するコード行を追加するのは簡単です。

NB:デザイナーは「when player.distance = 50」を望んでいないため、pub / subはこのIMEにはあまり適していません。 彼らが実際に望んでいるのは、「スクリーンを見ている人が感じるプレーヤーの距離が、最初の村、または少なくとも4画面幅右に移動したように見えるとき」です。 単純なカウンターよりもはるかに曖昧で抽象的な。

実際には、これはロジックが変更が発生するポイントに移動することを意味します(イベントが発行される前でもあります)。これはpub / subの使用方法としては不十分です。 「ロジックは受信の時点で進む」(「サブ」部分)を簡単にするゲームエンジンがいくつかありますが、それらは過半数ではありません。IMEです。

  1. オンラインゲーム:「カウンター」(int 上昇)、通常:「デルタ」(フレーム間で発生するフレームの循環バッファー)、および「イベント」(ゲーム内で発生した複雑な事象で、単一のIDと固定サイズにハードコーディングできる)パラメータの配列)。 これらは、他のサーバーのSNMPを介して公開され、低CPUコストで_非同期的に収集されます

i.e. 上記の1とほぼ同じですが、次の2つのことに注意してください。

  • 固定サイズのメモリ使用量。 「読み取り」サーバーがオフラインになった場合 その間に獲得した実績は再獲得する必要があります(通常、カスタマーサポート担当者がメインシステムログを手動で調べて、「おそらく」成果が獲得されたことを確認し、手動で授与することができます)

  • 非常に低いオーバーヘッド。 SNMPはこれに適した標準であり、ほとんどのチームは 結局それを使うことになります


1


ゲームアーキテクチャがhttp://en.wikipedia.org/wiki/Event-driven_architecture[Event-driven]の場合、http://en.wikipedia.org/wiki/Finite-state_machine [finite]を使用して実績システムを実装できます。 -ステートマシン]。