7

私はPolyworldに似たものを作成しています。つまり、小さなクリーパーが走り回ったり、食べたり、進化したりする仮想世界をシミュレートします。私はNode.jsでそれを作成しており、物理学とニューラルネットワークを使用する予定ですが、世界を更新するための最良の方法がわかりません。具体的には、更新関数が引数としてデルタ時間を受信する必要があります。または、最後に呼び出された日時に関係なく、毎回同じことをしますか?両方の方法の利点は何ですか?

編集: 継続的な更新に対して私が持っているポイントは、ある種の間隔を実装したいということです。たとえば、20シミュレーション秒ごとにフードブロックが生成されます。dtが1(または1の端数)と異なる場合、これは正確に機能しません。

繰り返しになりますが、更新が経過時間を気にしない個別の更新を使用する場合、「時間を遅くする」ことはできません。これを強力なサーバーで動作させ、ブラウザーでレンダリングするようにしたので、更新はかなり頻繁に行われると思います。シミュレーションに影響を与えずに時間を遅くする方法が必要なので、何が起こっているかを確認できます。

4

6 に答える 6

2

更新関数を呼び出すたびに、アニメーション開始からの経過時間を計算できます。次に、この時間を更新関数に渡すと、フレームが20秒で正確に更新されない場合でも、実際の時間に従ってすべての計算を行うことができます.

例: 車は速度 3units/s で 20 秒に動き始めます。更新関数が次の時点でトリガーされると仮定します: ...、19.35 秒、20.67 秒、... 20.67 秒の場合、車はすでに 0.67 秒移動していることがわかります。したがって、その位置 (時間 * 速度) 0.67 * 3 = 2.01 を計算し、他のすべての計算を行い、既に 2.01 単位移動したかのように描画します。このようにして、正確な時間測定、ラグ、通常よりも時間がかかる機能の更新などについて心配する必要はありません.

于 2012-08-29T06:48:25.380 に答える
2

複数のエージェント (それぞれに独自のスレッドを持つ) が連携する必要がなく、プロセス フローの問題の同期/イベントに対処する必要がない場合は、継続的なシミュレーションを使用することをお勧めします。固定時間ステップを使用して、各ステップで世界の状態を変更します。各ワールド ピースは、次のような関数を使用して状態を変更します。

newState = f(oldState, deltaSteps)

あなたが言及した速度の問題については、反復を時間に直接マッピングしないでください。中間の時間単位 (ステップ) を定義すると、この単位時間がミリ秒、反復、または好みにマッピングされます。したがって、シミュレーションの速度を上げたり下げたりする場合は、ステップから時間/反復への変換に使用される係数を変更するだけです。速度を変更する必要がある場合は、定数を変更してください。

このページをチェックして、シミュレーション手法に関する洞察を確認してください。

于 2012-08-29T18:15:17.870 に答える
1

特定の周波数 (50 Hz など) を超えていないと思います。これは、不要な精度で CPU 時間を無駄にします。

ユーザーのデバイスがその更新レートを提供できない場合は、次のいずれかを行います

  1. 同じ物理周波数を維持し、壁時計の速度を遅くする
  2. デルタ T を高くして物理周波数を下げる

周波数がまだ 20Hz を超えている場合は、2 にします。低くなった場合は、精度を維持するために戦略 1 に切り替える必要があります。

したがって、更新頻度を調整できるように、おそらく deltaT ベースのソリューションが必要です。

于 2012-08-22T22:39:29.147 に答える
1

更新関数は、タイム ステップごとに同じことを行う必要があります。

どちらのアプローチにも欠点がありますが、最後の更新からの経過時間を表すデルタを渡すと、母集団内で多対多の相互作用をシミュレートするときに管理が難しくなります。これは、相互作用が発生する時点 (デルタ) を予測するのに時間がかかるためです。これらの時点が失われると、シミュレーションは正確ではなくなります。

時間ステップごとにすべての要素を更新するアプローチの欠点は、不要な作業を行うことです。ただし、この不要な作業のコストは、特に複雑な相互作用環境を考えると、どの時点を評価する必要があるかを正確に予測するために必要な作業量よりもおそらく少ないでしょう。

于 2012-08-31T20:54:59.037 に答える
0

アニメーションを連続させ、経過時間またはクロックに基づいて(速度を上げたり下げたりできる可能性があります)したいと思うでしょう。そのため、デルタに基づいた更新関数がいくつかあります。

ただし、たとえば setInterval を使用して食品ブロックをスポーンできないという意味ではありません。また、他のすべてがそのデルタに基づいている必要がある、または基づいている必要があるという意味でもありません。

たとえば、位置の更新後に、互いに近くにいるクリーチャーや、生殖に必要な条件を確認してから、現在のクロックに依存しない個別のステップとして子孫を生成できます。ただし、それが起こったときの時計を記録したいと思うでしょう。

于 2012-08-29T08:59:00.457 に答える
-1

私は一定のタイムステップでこれを行います。はるかに簡単にコーディングできます。各更新関数は、環境に応じて 1 つのステップを実行します。各ステップでブラウザーを更新する必要はありません。10 または 100 ステップを計算し、結果をブラウザーに送信できます。

この方法ではるかに正確になります。小さな単純なステップの多くは、デルタ時間に依存する関数 (悪夢) よりもはるかに簡単にコーディングできます。

可変時間ステップを使用している場合。タイム ステップが大きい場合、アリが t0 で点 A に、t+delta で点 B にいるシナリオが考えられます。最初にアリを更新し、ポイント B で終了します。次に、t0+ 1/3 デルタでリスポーンする必要がある A と B の間の食物リスポーン ポイントを更新します。蟻は餌を見ずに通り過ぎました。シミュレーションが間違っています。

あなたがおそらく必要とする他のもの:

  • 本当に正確にするには、ポイントではなくセグメント [前の位置 - 新しい位置] 間の衝突をチェックする必要があります。そうしないと、アリが衝突せずに横切る可能性があります。物理エンジンをチェックします。
  • すべてのオブジェクトをブラウザに送信することは避けてください。八分木または四分木を使用して、ブラウザーに表示される領域に対応するデータのサブセットをすばやく判断します。

Node.js でこれを行うという奇妙な選択です。Java または実際の oop 言語を使用します。

ゲーム開発者フォーラムには、役立つヘルプがたくさんあります。

于 2012-08-30T21:32:24.630 に答える