MMOゲームで多数のピックアップを処理する方法


26

Minecraftのようなゲーム、または実際にピックアップを備えたMMOゲームはどのようにそれらを処理しますか?

地形を発掘するたびに、地形が3滴の「汚れ」を生成するとします。すべてのアイテムに、フレームごとに計算された回転アニメーションがあるとします。世界中のピックアップの数が非常に多くなると、それらのピックアップアイテムの多くがあなたから数年離れている可能性が高いため、特定のサーバーのクライアントのフレーム計算で無駄な大規模なオーバーヘッドになります。

だから私は、ローカルプレイヤーの近くにあるピックアップだけで「何かをする」必要があると考えましたが、それでも他のピックアップアイテムがアニメーションを開始するのに十分近いかどうかを確認する必要があるすべてのフレームを意味します。

私の実際の質問は、他のMMOがこの問題をどのように解決したかです。


9
さらに、Minecraftのコンテキストでは、特定の数のアイテムが互いに十分に近くなった後(同じブロックスペース内の同じアイテムの3+)、サーバーは3つのインスタンスをブロックタイプを含むグループ化されたインスタンスに置き換えます(minecraft:dirt)およびcount(30)。プレーヤーがそれを拾うのに十分近い場合、プレーヤーのインベントリにできるだけ多くのカウントを追加します。プレーヤーに6個のアイテムだけのスペースがあり、30のスタックが地面にある場合、プレーヤーは6をピックアップし、地面のカウントのスタックは24に減らされます
。– Zymus

6
@Zymus常に近くのアイテムを探しているため、中程度の数のドロップされたアイテムのティックパフォーマンスが実際に低下していることは注目に値します。
user253751

回答:


48

プレイヤーに近いメモリの世界の部分だけをロードするだけです。それ以外はハードドライブに一時停止されます。2キロメートル離れたところに小さなオブジェクトが置かれている場合、プレイヤーはそれを見ることができず、それと対話することはできません。したがって、レンダリングのために更新したりGPUに送信したりする理由はありません。オブジェクトとその相互作用範囲が小さいほど、ロードする必要があるプレーヤーの周囲の範囲が低くなります。

プレイヤーに近いものを見つけることについて:それは、空間ルックアップに最適化されたデータ構造に世界を保存することに大部分が要約されます。それらの適切な候補は、空間ハッシュ多次元ツリーです。


迅速な回答をありがとう。Unityを使用することを考えていたのは、トリガーコライダーをチェックするために何らかの空間分割を使用していると推測しているため、キャラクターの周りに1つの大きなサークルコライダーを作成し、その中のすべてのアイテムを「アニメーション化」します。これはあなたの答えを実装する方法ですか?私が間違っていたら訂正してください、乾杯!
アラカヌ

2
@Alakanu遠距離でオブジェクトを表示したいが、プレーヤーに近いときに特定の計算負荷の高い動作のみを実行する場合に使用できます(y軸を中心に何かを回転させるだけでもそれほど高価ではないはずです)。しかし、Unityでオープンワールドゲームを実装する際の実際の課題は、プレイヤーが世界を移動している間にゲームオブジェクトをインテリジェントにインスタンス化して破棄することです(さらに良いのは、インスタンス化や破棄の代わりにオブジェクトプーリングを使用することです)。
フィリップ

ええ、この状況ではオブジェクトプーリングが必須です:)よろしくお願いします!
アラカヌ

3
@Alakanuこの答えがそのゲームにどのように適用されるかについての詳細は、Minecraftの「Loaded Chunks」の概念を確認してください。
T.サー-モニカーの復活

1
これはピックアップだけに当てはまるわけではありません。プレイヤーから遠すぎるオブジェクトは、そのように扱うことができます。プレーヤーに近いオブジェクトもあります。完全なインテリアの家を想像してください。ただし、実際に家に入るまでレンダリングする必要はありません。
ジベラス

22

管理するものは大きく2つあります。

  1. サーバーは、正式な方法で全世界を管理する必要があります。そのためには、N個のクライアント(Nは「大規模」)との通信が必要です。

  2. クライアント、原則として、全世界について知ることができます、そうする必要はありません。クライアントにとっては、プレイヤーの近くに何があるかを知るだけで十分です。たとえば、かなり粗いグリッドのようなパーティション分割を想定すると、プレーヤーのセルとプレーヤーの周囲の26個のセル(2Dグリッドの場合は8個のセル)のみを知る必要があります。多少細かいグリッドの方が優れていますが、アイデアは得られます。

さて、たくさんのピックアップ、「たくさん」とは何ですか?1秒間に5つのことを掘ることができます。これは、サーバーで更新する必要のある数十の数値であり、サーバーそれらがセルと重なっている他のプレイヤーにそれらを送信する。コンピューターにとって、これは非常にばかげた量のデータであり、無視できる量の計算です。同じセルに何百人/何千人ものプレイヤーがいる場合、それが課題になる可能性があります(その場合、パーティショニングが粗すぎます)。

サーバーは、ピックアップの回転やそのような詳細を知る必要も、気にする必要もありません。なぜだろうか?

クライアントは実際には気にしません。これは、クライアントがその場で補うことができる単なる見た目だからです。

サーバーの観点から必要なのは、あなたがいるノードで(30、40、50)を掘っていたことを知ることであり、これにより、例えばタイプ5の3つのオブジェクト、または3のカウントです。これですべてです。また、関心のある領域を後でグリッドセル上で移動する人に送信されるデータにその情報が含まれます(それまでにまだ存在していると仮定します)。

クライアントは、そこに生成された3つのオブジェクト、何とか言った。これで、クライアントが「D」のある場所にASCIIアートマップを表示するか、回転する汚れの山を表示するかは、すべて同じです。パイルの回転が異なるかどうか、またはプレーヤーに近いものだけが回転するかどうかも同じです。モニターに表示されるのは単なるもので、他の人には影響しません。

そのため、近くの汚れの山だけを回転させたいという具体的なケースでは、知っているすべてのオブジェクトの範囲チェックを行うことができます。データセットは大きくないため、すべてに対してブルートフォースでも機能します。

パーティションのサイズに応じて、あまりにも遠くにあるグリッドセルを簡単に取り除くことができます(する必要があります)。

もちろん、セルをさらに分割して、非常にスマートなものを使用することもできます。必要に応じてkdツリーを使用しますが、大きな利益は期待しません。Manhattan distaceで整理することも、自分の小さなグリッドで整理することもできますが、なぜですか?

距離チェック(実際には二乗距離ですが、あなたにとっては同じです)は、2回の乗算と加算(MUL、MADDに最適化されているため、実際には2つの操作のみ)で、その後に分岐または条件付き移動が続きます。これは、グリッドセル全体を一度に削除しない他の操作とほぼ同じくらい高速です。実際、これはGPUでも実行できることです...

同じ位置に対して数百、またはせいぜい数千の距離チェックを行う方法を見ると(2乗距離は問題なく機能します)、その計算を実行するだけで問題はありません。連続したメモリに対する友好的な反復、および条件付きの移動により、コストは安くなります。(疑似コード)のようなものrot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];。これは、フレームあたり数百の値の配列に対する1回の繰り返しです。コンピューターはそれを行うことにあまり関心がなく、連続したロードとストア、単純なALU、ブランチなし、数千回の反復です。

これは(多対1)サーバーの問題と同じクラス(多対多)ではありません。本当に、クライアントは問題ではありません。


申し訳ありませんが、フレームレートについて話し始めたとき、私はクライアントについて話していたことは明らかだと思いました。
アラカヌ

1
しかし、クライアントが問題になることはありません。クライアントは非常に非大規模で、非常にローカルであるため、サーバーよりもはるかに少ない情報を知る必要があります。理想的には、クライアントはプレーヤーがいる空間分割ノード(グリッドなど)を知っていて、そのすぐ近くにあるものを知っていれば、それで終わりです。したがって、更新は、千人のプレイヤーが隣り合っていない限り、非常に控えめです。通常、1つまたは2つのオブジェクトのデルタと、ノードの幅の半分以上で一方向に移動した後の新しいグリッドノードのコンテンツのみが必要です。その他:あなたの問題ではありません。
デイモン

1
重要なのは、賢すぎるというのは非常に愚かな考えであるということです。あなたの世界は必然的に空間的に既に分割されており、各ノードには管理可能な数のオブジェクトがあります。最新のCPU(さらにGPU)は、大量のSoAデータを順次処理するのに適しています。彼らは支離滅裂分岐好きではない、と彼らさえ少ないインコヒーレントメモリアクセスのように-しかし、ある正確「だけ近くの処理」何が行います。管理可能な数(数百、数千)の場合、1つのセル内の「すべてを処理する」ことは完全に適切であり、おそらく最善のことです。
デイモン

1
@Alakanuこれは、私にとってあなたの質問に対する詳細かつ完全な答えのように見えます。あなたがそれが答えではないと思うなら、あなたはそれを誤解したか、あなたの質問が非常に不明瞭であるため、デイモン、私、そしてこの答えを支持したすべての人々によって誤解されています。
デヴィッドリチャービー

2
@Alakanuあなたは本当にあなたを助けようとしている人々に文句を言うのに膨大な時間を費やしています。それで頑張ってください。
デビッドリチャービー

2

@ T.Sarはコメントで、詳細についてはMinecraftsの「読み込まれたチャンク」の概念を調べる必要があると書いています。その場合、これはMinecraftではゲームで機械を構築する人がいるため、かなり複雑であることに注意してください。

非常に簡略化されたバージョンは次のとおりです。

世界は正方形の領域(チャンク)に分割されています。Minecraftには高さ区分もありますが、ほとんどのmmosはそれを必要としません。

ゲームクライアントは、プレーヤーに近い地域のみを考慮します。これは、プレーヤーの周りに円を描くよりもはるかに簡単ですが、完全に十分です。

Minecraftでは、領域は16x16ブロックであり、クライアントは各方向に4つの領域がある9x9の領域について知っています。(東部4リージョン+リージョンプレイヤーは西部4リージョン=合計9リージョンです。同じ北/南)

これらの数字には魔法のようなものは何もありません。ゲームで意味のあるものを使用してください。

クライアントはこの領域内の物だけをアニメーション化します。サーバーは、一部のプレイヤーに近い地域でさまようモンスターのようなものだけを計算します。

プレーヤーがリージョン内を歩き回っても、特別なことは起こりません。リージョンの境界を越えると、「アニメーションのエッジ」が1リージョン上にプッシュされます。次に、クライアントは、現在表示されているリージョンについてサーバーに問い合わせる必要があります。

いくつかのネストされたアニメーション制限を設けても問題はありません。たとえば、3x3のエリアにアイテムをドロップし、5x5のエリアにモンスターをさまようと、9x9のエリアに風景を表示します。

サーバーは、プレーヤーが見ることのできないリージョンの「凍結バージョン」を保持します。これに大量のメモリが必要な場合は、しばらくしてからこれらをアンロードすることをお勧めします。プレイヤーが次に到着すると、アイテムはドロップせずにリージョンがリロードされます。次回はプレーヤー1の速度を上げる必要があります。


描画距離は調整可能ですが、この場合、8チャンクは9x9であり、クライアント側の決定であり、速度を上げるようにサーバーに通知できます(したがって、サーバーはクライアントがレンダリングしないデータを送信しません)。また... DoomとQuakeは、意味のあるものだけをレンダリングするという問題を解決しませんでしたか?
-SparK

ドロップされたアイテムのデスポーンについて... Minecraftでは、プレイヤーが近くにいるときにのみアイテムが「エージング」します。したがって、ドロップされたアイテムをアンロードされたチャンクに「保存」して、後で取得することができます。
SparK
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.