大きなタイルマップ上のエリアとダンジョンを「ゾーニング」


10

私のゲームは、疑似無限でランダムに生成される方法で、Minecraftのようなマップを持っています。そして大きい。ユーザーが1000x1000ゾーン(ここでは2D)を探索したとすると、1,000,000タイルになります。

もちろん、すべてをメモリに保存することはできません。また、10タイルまたはすべての半径からすべてを無視したくありません。どちらも更新されず(すべてのNPC、おそらくリアクティブタイル)、1382、12918のような厄介な位置で作業する必要があります。

したがって、チャンクやゾーン、または64x64タイルなどに分割する場合、各タイルとオブジェクトの位置を次のように保存する必要があります。

チャンクa、b。位置x、y。

しかし、マップにダンジョンなどが必要な場合はどうなりますか?つまり、それぞれが40x40の面積を持つ40階のダンジョンにつながる単一のタイルです。それらを同じマップに正確に格納することはできません。

そして、記憶の側面があります。どのくらいの量を同時に合理的に同時にメモリに格納できますか?IDでタイルを簡単に作成でき、そこに通常の2D配列を配置できます。または、タイルタイプのデータファイルよりも効果的な解決策はありますか?したがって、64x64の場合は、20K程度になるでしょう。最も現実的な更新のために、できるだけ多くの環境が読み込まれるようにしたいと思います。しかし、私は、メモリの浪費になることなく、どのような制限に達することができるのかわかりません。

回答:


9

「実証済みの問題でない限り、心配する必要はありません」という意見には同意しますが、早い段階で検討する価値はあると思います。そして、はい、「近くの」タイルを更新することだけが彼らの行く方法です。ただし、パフォーマンス上の理由から、ゲームの世界でアイテムを効率的に格納およびアドレス指定できることは非常に重要です。

ここで実際に考えているのは、スパースデータセットです。潜在的なインデックスは大きい(または無制限)が、実際に使用される割合はわずかなものです。重要な点は、どの比率を使用するかが正確にわからないことです。

スパースデータセットの問題に対する標準的な解決策は、インデックス/アドレス可能度を実際のデータストレージから分離することです。そのため、タイルオブジェクトが高価な場合は、コンパクトな形式(フラット配列など)で保存します。ただし、より安価なオブジェクトを介してインデックス付けできるようにします。最も単純な形式では、これは座標で簡単にインデックス付けできる2D(または3D)マトリックスにすることができますが、マトリックス内の各アイテムは単なるインデックスです。次に、そのインデックスを使用して、実際のタイルの内容を別のコンパクトな配列で検索します。タイルのコンテンツがまだ存在しない場合は、それらを配列の最後に追加し、3Dマトリックスにインデックスを格納します。

コンテンツの削除をサポートする場合(コンテンツ配列の断片化につながるため)、タイルコンテンツが安価な場合、インデックスの追加の重み(32ビットまたは64ビットのインデックス)の場合、ソリューションはより複雑になります。可能性のあるすべてのタイルを保存しないことによる節約をおそらく圧倒します。これは追加のルックアップでもあり、キャッシュのパフォーマンスを低下させます。

インダイレクションの追加レイヤーを導入することで、ストレージ効率をさらに高めることができます。タイルをチャンクに編成し、チャンクの粒度が64x64x64であるとします。タイルが125、1、132の場合、チャンク(1,0,2)に属していることがわかります。したがって、コンパクトなチャンク配列とチャンクインデックスのマトリックス(チャンクが存在しない場合は-1)で構成されるワールドがあります。各チャンクのコンテンツ(存在する場合)は、タイルインデックスの64x64x64マトリックス(タイルがまだ存在しない場合は-1)と使用されるタイルのコンパクトな配列です。このようにして、使用されていないチャンクに対して大量のタイルインデックスを焼き付けることはありません。このようなアプローチに従い、チャンクの粒度に適切な数値を選択することで、ユニバースを大幅にスケールアップし、メモリ使用量を制御することができます。実際、チャンクを32x32x32にすると、

チャンクの高次ビットまたはタイルインデックスを使用して特別な何かを意味するような、卑劣なトリックを行うこともできます。したがって、タイルマトリックスのエントリに上位ビットが設定されている場合、下位31ビットはタイルインデックスを意味するのではなく、「ワープインデックス」または類似のものを意味します。これは、個別に維持されるリストで調べることができます。それが導く座標を見つけるために。


将来この質問に遭遇する人には注意してください。この投稿の内容に誤りはありませんが、Minecraftのような、スパースな世界を持たないゲームにとっては正直恐ろしいことです。(そしてMrCrankyも同じように語っています。)あなたの世界がこれから恩恵を受けるのは、いくつかの何かがあり、何もないものがたくさんあり、いくつかの何かがなく、がたくさんない場合だけです。

1
スパースデータセットのストレージソリューションの維持に伴うオーバーヘッドがかなり高いため、バランスがスパース性に明らかに偏っている場合にのみ使用することに同意します。ここでの重要な要素は、データ項目のコストとデータ項目が使用されない確率です。Minecraftには膨大で潜在的なデータセットがあります(各方向にいくつものタイルがいくつかあります)。使用される可能性のあるゲームの世界の実際の割合はごくわずかです。世界中を移動しているときに大きなスワスを主張するとしても、それは潜在的なデータ項目のごく一部です。
MrCranky、2010

1
Minecraftの違いは、ユニットあたりのコストが小さいことです-それはたぶん1バイトのストレージですか?1つの値は「何もない」ことを示し、残りはブロックタイプであり、バイトに簡単に合わせることができます。したがって、単一のブロックへのインデックスはありません。それは狂っています。インデックスは、実際のブロック値を格納するよりもはるかに大きいです。ただし、スパースデータセットのルールは、より高いレベルでも機能します。各チャンク(例:64x64x64)は格納するのにコストがかかります(256Kブロック)。そのため、1つの小さな値を使用してそれがないこと、または存在する場合はそのアドレスを示すことができれば、大容量のストレージを節約できます。
MrCranky、2010

6

100万タイルをメモリに保存できないのはなぜですか?私の電話にも256MBのRAMがあります。100万の空のタイルは、4〜32 MBになりますか。


保存するのは非常に多くのように思えました。それだけでなく、それらを更新するのにも長い時間がかかります。
共産主義者のダック

2
ある種のディスクページングソリューションを処理するよりも、更新用のタイルのセットを無視する方がはるかに簡単です。それらを無視してください。既知の俳優からX距離を超えるタイルを更新しないでください。

2
@TheCommunistDuck重要なのは、タイルの数ではなく、タイルの格納に使用されるメモリの総量です。
ジャスティン

1
クラゲンとジョーに同意した。よく聞こえることについて心配する必要はありません-数学をやってそれを解決してください。問題になることはほとんどありません。
Kylotan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.