携帯電話を別の方向に移動させるために、どのようなステアリング動作またはロジックを使用できますか?


10

ゲームでパスファインディングを使用して、暴徒を別のプレーヤーに誘導しています(追跡するため)。これはそれらをプレーヤーの上に乗せるために機能しますが、目的地の少し前に停止させたいので(最後から2番目のノードを選択しても問題ありません)。

ただし、複数のMobがモバイルを追跡している場合、「互いの上に積み重なる」ことがあります。これを回避する最良の方法は何ですか?モブを不透明でブロックされたものとして扱いたいわけではありません(そうでないため、ウォークスルーすることができます)が、モブに構造的な感覚を持たせたいです。

例:

それぞれのヘビが私を案内し、「セツナ」を囲んでいると想像してください。両方のヘビが私を突き刺すことをどのように選んだかに注意してください?これは厳密な要件ではありません。少しずれていても大丈夫です。しかし、彼らはセツナを「取り囲む」べきです。

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


1
積み重ねは目的地でのみ問題ですか、それとも輸送中ですか?後者だと思います。
SpartanDonut 2014

後者です、@ SpartanDonut
Vaughan

@KromStern写真を追加しました。
Vaughan Hilts 2014

回答:


15

エージェントに弱い「静電気」を与えて、クーロンの法則に沿って、エージェントを互いに反発させます。

暴徒は、同等の強度で互いに離れをプッシュする必要があることを簡単にするために仮定すると、大きさで暴徒のすべてのペアの間に力を適用するために十分である必要がありsome_constant / distance^2some_constant設定可能な反発力で、distanceそれらを隔てる距離です。

反発力は、距離の2乗で減少します。

Nature of Codeは、ここに(ライブデモを含む)良い例があります。次のようになります。

追跡動作と個別動作の組み合わせ

すべての要素を互いに照合することは、2次時間(O(n^2))操作です。あなたが持っている場合は、本当に多くの薬を、あなたが力の計算を最適化することを望むかもしれないバーンズ・ハット近似対数線形ためにそれを取る(、 O(n log n))が、必要と四分木を


素晴らしいリンク、Anko。大変感謝いたします!私は間違いなくこのサイト全体を読み返さなければなりません。
Vaughan Hilts 2014

スタークラフト(少なくとも1つ)は、その飛行ユニットと同様のことを行います。しかし、それは彼らが動きを止めたとき、つまり彼らが動いているとき、彼らが互いの上に群がっているとき(完全に障害物としてお互いを無視する)だ​​けですが、彼らが止まるとき、彼らはすべてのように見えるものから広がり始めますそれらを囲むいくつかの通常の領域(おそらく正方形/円)のローカル中心。これは回答の例ほど美しくありませんが、CPUリソースの使用量が少なく、コーディングも簡単です...
Shivan Dragon

@ShivanDragon SC2は同じ動作を示し、すべてが群集の中で目的地に収束し、次に、現実に近い、美しく魅力的な外観のために間隔を空けます(そのため、それらのパーツは動きません)。
Kroltan 2014

2
ある種の反発力は良い考えですが、詳細は注意が必要です。私はこれらを宇宙をテーマにしたRTSで実験しました。物理学をあまり厳密に追跡するのではなく、むしろそれがうまく機能するようにモデリングすることをお勧めします。いくつかの観察:1)これは物理シミュレーションではないので、私は力を短い距離にのみ適用します。2)これは有限体の重なりを防ぐことはできません。3)ハードポテンシャルは、粒子が高速で屈折するなどの数値エラーを簡単に引き起こします。4)かなりの数のパーティクルがあり、中間の圧力が上昇すると、状況は醜くなります。
CodesInChaos 2014

1

私のアプローチは@Ankoのアプローチと似ていますが、Artificial Intelligence for Gamesの MillingtonとFungeの研究に基づいています。

これは、分離動作がどのようになるかですが、この速度は、更新機能でエージェントの速度を使用して計算する必要があることを考慮する必要があります。

public Vector3 GetSeparationVel (float threshold, float decayCoefficient)
{
    threshold = threshold * threshold;
    Vector3 separationVelocity = Vector3.Zero;
    for (int i = 0; i < enemies.Length; i++) {
        if (enemies[i] == this) {
            continue;
        }
        Vector3 direction = this.position - enemies[i].position;
        float distance = direction.LengthSquared();
        float strenght = 0.0f;
        if (distance < (threshold)) {
            strenght = Math.Min(decayCoefficient / distance, this.maxAccel);
            direction.Normalize();
            separationVelocity += strenght * direction;
        }
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.