トラクタービームを実装するには?


8

私は、プレイヤーがトラクタビームのようなものを使用してオブジェクトを拾い、それらを持ち運ぶことができるゲームに取り組んでいます。

ビームの中心に向かってオブジェクトを引き付けることは難しくありません。しかし、オブジェクトが中心に十分近づいたら、プレイヤーが動いている間、オブジェクトをそこに置いておく必要があります。これが問題です。それを行うには2つの方法が考えられますが、どちらにも問題があります。

  1. プレーヤーの位置が変更されるたびにオブジェクトの位置を更新し、ビームの中心に配置します。

  2. オブジェクトの速度を更新して、ビームの中心を直接指すようにすると、遠ざかるほど速度が上がります。

移動と回転はどちらの方法でも問題なく機能しますが、運ばれたオブジェクトが他のオブジェクトと衝突すると、物理学は正しくありません。

最初のアプローチでは、物理学は完全に無視されます。運ばれたオブジェクトは、何でも邪魔にならないように押し出します。位置の変更は、速度に基づいて、世界の物理学の一部としてのみ行われることになっているためです。

2番目のアプローチでは、物理学は基本的には本来あるべき振る舞いをしますが、過剰反応します。問題は、回転して移動しているときでも、運ばれたオブジェクトをビームの中心に保つために、高い速度値を使用する必要があることです。したがって、運ばれたオブジェクトが別のオブジェクトに触れると、衝突によって速度が大きくなりすぎます。

これを適切に実装するにはどうすればよいですか?現在の私の推測では、2番目のアプローチを使用して、運ばれたオブジェクトの特別な処理をワールドフィジックスに追加し、衝突時またはプレーヤーが持ち運びを停止したときに速度を正解値に下げることです。しかし、それはかなり洗練されていない回避策のようです。

編集:いくつかの疑似コードを追加して、それが現在どのように機能するかを示します(上記の2番目のアプローチになります)

void attract_object(object, ticks) {
    Vector distance = beam_center - object.center;
    // If the object is not close to the beam center, attract it slowly
    if (magnitude(distance) > 10) {
        object.velocity += distance.normalized() * ticks * 0.1;
        return;
    }

    // Here comes the part we're talking about. That magic 0.5 is just high enough
    // that the object isn't lost while moving around. But it's still so high that
    // other objects are repelled with way too much force.
    object.velocity = distance * ticks * 0.5;
}

私が見るところから、これは運ばれたオブジェクトが別のオブジェクトを押しのけるときに起こります:

  1. 運ばれたオブジェクトが別のオブジェクトと衝突する
  2. オブジェクトの速度は適切に分散されているので、運ばれたオブジェクトはプロセス中にビームの中心から押し出されます
  3. 上記のコードは、運ばれたオブジェクトをビームの中心に戻します。速度が非常に高いため、すぐにそこに戻ります。
  4. 運ばれたオブジェクトがビームの中心に向かって戻ると、その高速の半分が他のオブジェクトに転送され、激しく反発します。運ばれた物体の初速は良さそうなので、手順2〜4が何度も繰り返されて、こんなに高い速度がつくのではないでしょうか。

それが原因のようです。私はそれを修正するための良い方法を考えることはできません:(


1
トコマク核融合炉の複雑さへようこそ。磁気ボトルではなく、数学モデルを作成するだけでよいという利点がありますが、数学は同一であり、自明ではありません。あなたがしようとしていることは実行可能ですが、コーディングの前に数学モデルを綿密に検討する必要があります。
Pieter Geerkens 2013

回答:


1

基本的にあなたが探しているのは、あなたが手でそれをつかむかのように、「ビームされた」オブジェクトを正確に振る舞わせることです。
1つのオプションは、ビームの中心でギャップを満たすために速度を調整する代わりに、それを保持する「手」の加速度と速度を共有することです。

ビームの中心が持ち手であるとしましょう。キャラクターが1秒で左に90度回転した場合、手の速度は次のようになります。

If R = length of the arm: which is the radius of the rotation circle
R^2 *PI /4 would be the distance traveled over a second.
オブジェクトに適用する必要のある速度を見つけるために、フレームの経過時間に時間をかけます。方向ベクトルを見つけるために、ビームの水平法線を見つけます。

私の要点は、そもそもそれを引き起こさない他の実装を試しても問題を解決する必要がないということです。

この問題についてインスピレーションを得るためにHL2の重力銃を使って遊びますが、今日は他の計画があります。

編集:申し訳ありませんが、それは3Dビームガン用だと思っていましたが、軸が異なることを除いて、基本的に2Dと同じです(そして複雑なジオメトリはありません)


さまざまなハックを試みた後、これは私を軌道に乗せたものであり、結果は良く見えています。衝突の速度はまだ少し高すぎますが、私はそれを理解できると思います。おそらく、高速でオブジェクトを別の方向に引き付けないことだけです。
futlib 2014年

おそらく、「手」が壁に衝突しているときに、手に最も近い(衝突していない)もっともらしい位置を計算し、衝突が発生している間、これを「一時的な手」として使用できます。私はしばしば別の視点から問題に取り組むのが好きです。私はそれを助けることができてうれしい;)。
icosamuel 2014年

4

スプリング接続を追加するのはどうですか。つまり、運ばれたオブジェクトを距離に基づいてキャリー位置に強制的に戻しますが、それでも固体(壁など)によって押しのけられるようにします。

(位置/距離に基づいて加速度を変更することにより)運搬されたオブジェクトの速度を常に調整して、トラクターのビームの位置に向けます(つまり、2番目のアプローチ)。オブジェクトが離れすぎている場合は、接続(およびオブジェクト)をドロップします。

なぜ高速が必要なのかよくわかりません。特に「プレーヤーが手放す」ケースは、回転速度が速すぎるか、非現実的である可能性があることを示します。また、空気抵抗や重力などを忘れないでください。


編集:更新されたコードを考えると、問題は見つけるのは簡単です:

if (magnitude(distance) > 10) {
    object.velocity += distance.normalized() * ticks * 0.1;
    return;
}

ここでの問題は、目標位置までのオブジェクトの距離が常に遠すぎる(つまり> 10)場合です。この条件が満たされている限り、その速度は単純に何度も(つまり無期限に)増加します。

これに対する2つの可能な解決策:

最大速度を定義します。

object.velocity = min(object.velocity + distance.normalized() * ticks * 0.1, max_velocity);

加速するのではなく、固定速度を適用します。

object.velocity = distance.normalized() * ticks * magic_factor;

ここでは、遠すぎて加速するのは間違いです。ばねまたは輪ゴムを引くことに関すること:1秒間保持しても1分間保持しても問題ありません。結局、それは同じように加速します(動かされておらず、他に力が加えられていないことを考えると)。


これが方法2で説明したものではありませんか。それが基本的な春の物理学です。上記の質問にコードを追加して説明します。
futlib

上記の誤った速度に関する部分も削除しました。実際には問題ありませんが、テストしただけです。したがって、混乱しているのは、他のオブジェクトとの衝突だけです。
futlib

はい、本質的には2番目のアプローチです。回答を更新しています。
マリオ

両方の方法を試しましたが、役に立ちません。マグニチュード(距離)> 10のケースはここでは原因ではないようです。<=ケースの速度を制限してみましたが、それは通常の問題です。速度が非常に低いため、オブジェクトがドロップされているか、非常に高いため、他のオブジェクトを激しく反発しています。
futlib

「他のオブジェクトを激しく反発するほど高い」:シーンの背後の速度ではなく、実効速度に基づいて他のオブジェクトを移動する必要があります(つまり、衝突による速度のリセット)。
マリオ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.