エンドレスランナーで実際に動いているものは何ですか?


107

たとえば、有名なゆるい鳥のゲーム、または実際に並べ替えるものは、プレイヤー(この場合は鳥、またはカメラのどちらか好きな方)が前方に移動するか、全世界が後方に移動します(鳥はY位置のみを変更し、一定のX位置)?


1
この質問とその回答から、トピック外のコメントを多数削除しました。また、いくつかの合理的な議論をチャットに移動し、場合によっては繰り返しました。それにもかかわらず、コメントは拡張討論用ではないという事実を無視する必要性を感じているユーザーがいます。そのため、この質問は一時的にロックされています。
ジョシュ

回答:


146

私はフィリップの答えに少し同意しません。または少なくとも彼がそれを提示した方法で。プレイヤーの周りで世界を移動することは良いアイデアかもしれないという印象を与えます。それが正反対であるとき。だからここに私自身の答えがあります...


どちらのオプション機能します、一般的には、世界中のプレイヤーではなく、プレイヤーの周りで世界を動かすことによって「物理学を逆転させる」ことは悪い考えです。


パフォーマンスの損失/無駄:

通常、世界には多くのオブジェクトがあります。ほとんどではないにしても、多くは静的またはスリープ状態です。プレーヤーには、1つまたは比較的少数のオブジェクトがあります。プレーヤーの周りで全世界を移動するとは、プレーヤー以外のシーン内のすべてを移動することを意味します。静的オブジェクト、スリープ中の動的オブジェクト、アクティブな動的オブジェクト、光源、音源など。すべて移動する必要があります。

それは(明らかに)実際に動いているもの(プレーヤー、そしておそらくさらにいくつかのもの)だけを動かすよりもかなり高価です。


保守性と拡張性:

プレーヤーの周りで世界を移動すると、世界(およびその中のすべてのもの)が最も活発に起こっているポイントになります。システムのバグや変更は、潜在的にすべてが変更されることを意味します。これは物事を行う良い方法ではありません。バグ/変更をできる限り隔離して、変更を加えていない場所で予期しない動作が発生しないようにする必要があります。

このアプローチには他にも多くの問題があります。たとえば、エンジン内で物事がどのように機能するかの多くの仮定を破ります。RigidBodyたとえば、プレーヤー以外にダイナミックを使用することはできません。添付を持つオブジェクトとしてRigidBody位置/回転/スケールを設定するとき動に設定されていませんが(😨プレイヤーを除いて、あなたはシーン内のすべてのオブジェクトのために、すべてのフレームをやっていると思いますどの)予期しない動作をします


答えは、そのときプレーヤーを動かすだけです!

まあ... はいいいえ。Philippの答え​​で述べたように、無限ランナータイプのゲーム(またはシームレスで探索可能な領域が大きいゲーム)では、原点から離れすぎると、最終的に顕著なFPPE(浮動小数点精度エラー)が発生し、さらに、数値型をオーバーフローさせて、ゲームをクラッシュさせるか、基本的にゲーム世界の煙をクラックさせます... ステロイドで!😵 (この時点までに、FPPEはゲームを既に「通常の」クラック状態にするため)


実際のソリューション:

どちらもせず、両方をしてください!ワールドを静的に保ち、プレーヤーを動かしてください。しかし、プレーヤーがシーンのルート(位置から離れすぎ始める、プレーヤーワールドの両方を「再ルート」します。 [0, 0, 0]

物事の相対位置(周囲の世界に対するプレイヤー)を保持し、このプロセスを1回のフレーム更新で行うと、(実際の)プレイヤーは気づきさえしません!

それを行うには、2つの主要なオプションがあります。

  1. プレーヤーをシーンのルートに移動し、ワールドチャンクをプレーヤーに相対的な新しい位置に移動します。
  2. 世界をグリッドのように考えてください。プレーヤーがいるグリッドの部分をルートに移動し、グリッドのその部分に相対的な新しい位置にプレーヤーを移動します。

このプロセスの実際の例を次に示します


しかし、どのくらい遠すぎますか?

Unityのソースコードを見ると、2つの浮動小数点値「等しい」、および(オブジェクトの位置、[オイラー]回転、およびスケールを担当するデータ型)の内部を考慮するための基礎として1e-50.00001)を使用します。浮動小数点精度の損失はゼロから両方向に発生するため、シーンのルート/オリジンから離れた()ユニットより下のものは安全に処理できると想定するのは安全です。Vector2Vector31e+5100000

しかし!以来...

  1. これらのルート変更プロセスを自動的に処理するシステムを作成する方が適切です。
  2. あなたのゲームが何であれ、世界の連続した「セクション」が100000単位(メートル[?])幅である必要はありません。

...その場合、おそらく100000ユニットよりもはるかに早く/頻繁にルートを変更することをお勧めします。私が提供したビデオの例は、たとえば、1000単位ごとに実行するようです。


2
コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました。ここにコメントを投稿する代わりに、そのチャットを使用してください。
アレクサンドル・ベイランクール

> それは(明らかに)実際に動いているものだけを動かすよりもかなり高価です<それですか?レンダリングするときは、とにかくだろうアイデンティティに固定カメラを持つ、すべてのオブジェクトに対するカメラ行列と行列の乗算を行う必要があります以下、このように高価。
Matsemann

その瞬間ゲーム開発は、ユニティ・開発になり...
LJᛃ

@Matsemann-チャットに行ったことがあれば、これが新しいポイントではないことに気づいたでしょう。すでに説明したように、NOT-EQUALSシーンをレンダリングします。それらは異なり、ほぼ完全に独立した主題とパイプラインです。シーン内でオブジェクトを配置する方法で参照フレームの反転を行うと、単にレンダーするのではなく、両端でより重いプロセスを持つことになります。---また、も、あなたが主張するなどの性能が等しく、取引された場合は、すべての他の反転との問題が考え、まだそのアプローチを作り、未解決のまま、まだ再発根1より悪いです。
XenoRo

@LJᛃ 統一についての質問が具体的に行われたので(D. Everhardの[IMHOデフェーシング]編集前のOPのタグを参照)、その答えはそれを反映するように調整されました。---しかし、ここが最良の部分です。Unity、Unreal、CryEngine、Sourceなどになります。最高および/または最も人気のあるエンジンは、この方法で動作します(そして、それらは理由のために動作します)。一般に完全に有効ですが、行われているポイントはまだ正確さの頂点にあります。一般的に、物理学の参照フレームを逆にすると、特に動的オブジェクトで問題が発生することが予想されます。
XenoRo

89

両方のオプションが機能します。

しかし、無限のランナーを本当に無限にしたい場合は、プレーヤーを動かないようにし、世界を動かす必要があります。そうしないと、最終的に、X位置の格納に使用する変数の制限に到達します。整数は最終的にオーバーフローし、浮動小数点変数の精度は次第に低下し、しばらくするとゲームプレイが不安定になります。ただし、1回のセッションでおそらくプレイできるタイムスパン内で誰もこれらの問題に遭遇しないほど十分に大きいタイプを使用することにより、この問題を回避できます(プレイヤーが1秒あたり1000ピクセル移動すると、49日後に32ビット整数がオーバーフローします)。

概念的に直感的に感じるものなら何でもしてください。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ジョシュ

1
私はそれが何も解決するとは思わない。プレイヤー(およびカメラ)の位置を維持する代わりに、世界のスクロール位置を維持します-どのように違いますか?
Agent_L

1
@Agent_L一般に、ワールドは断片的に生成され、各断片にはX / Y位置があります。ピースがプレーヤーの背後(スクリーン外など)に十分に遅れると、削除され、事前に特定の量だけが生成されるため、常に比較的小さな範囲内に収まります。無限にランダムに生成されたランナーであるにもかかわらず、〜1000未満または0未満です。そのため、各チャンク内のプレーヤーの位置と、シーケンス内の各チャンクのインデックスを追跡しました。
ニックハートリー

「変数オーバーフロー」の概念は購入しません。プレーヤーが動いていない場合、プレーヤーが動いていた場合に相殺されるのと同じ量だけ「背景」が負に相殺されます。どちらの場合もまったく同じ問題が発生し(反対方向)、オーバーフローの限界で特別な処理が必要になります。
支出者

2
1秒あたり1000ピクセルの場合、64ビット整数を超えるには5億8600万年以上かかります。これは、16ビット整数のような非常に小さな型を使用している場合にのみ本当に問題になります。
リンドンホワイト

38

オフビルXenoRoの答えの代わりに1は、次の操作を行うことができ、彼らは説明再発根方法、の、:

生成された無限マップの一部の循環バッファーを作成します。モジュラー演算で更新された位置でキャラクターが移動します(したがって、循環バッファーをただ走り回るだけです)。キャラクターがチャンクを離れるとすぐに、バッファーの一部の交換を開始します。プレーヤーの更新式は次のようになります。

player.position = (player.position + player.velocity) % worldBuffer.width;

ここに私が話していることの絵の例があります:

ここに画像の説明を入力してください

最後にラッピングで何が起こるかの例を示します。

ここに画像の説明を入力してください

この方法を使用すると、これまで精度エラーに遭遇することはありませんが、非常に遠い距離で3Dでこれを行う場合は、非常に大きなバッファを作成する必要があります(まだ自分の前で見ることができる必要があるため))。ゆるい鳥の場合、チャンクサイズはおそらく、1つの画面で1つのシーンを保持するのに必要なサイズに過ぎず、バッファーは非常に小さくなります。

あなたが持つ結果、繰り返し取得を開始することに注意してくださいANY PRNGをし、PRNG世代の非繰り返しシーケンスの最大数は、捕虜の長さよりも一般的に少ない(2、内部で使用されるビット数)、とmerzenneツイスターこれではありません2.5kの内部状態を使用するため、多くの問題がありますが、小さなバリアントを使用する場合、繰り返しの前に最大2 ^ 127-1の繰り返し(またはさらに悪い)がありますが、これはまだ天文学的に大きな数です。PRNGの期間が短い場合でも、シードに対する適切な雪崩混合機能を使用して(暗黙的に状態を追加するにつれて)繰り返し期間の問題を繰り返し修正できます。


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ジョシュ

15

すでに尋ねられ受け入れられているように、それは本当にあなたのゲームの範囲とスタイルに依存しますが、言及されていないので:FlappyBirdは世界中のプレイヤーではなく、画面を横切って障害物を動かします。

スポーナーは、一定の速度でオブジェクトを画面外にインスタンス化しますVector2.left


3
FlappyBirdでは非常にシンプルなゲームであるため、これは機能します。私の答えで述べたように、同じ手法はまだ可能ですが、Subway Surferのような、より複雑な(より多くの世界オブジェクト/詳細を持つ)ものでは非常に問題になります。
XenoRo

15
私は同意し、あなたの答えは非常に徹底的です。私は、羽ばたき鳥が実​​際に使用する方法について誰も言及していないので、私はそれを追加すると思いました。
ステファン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.