web-dev-qa-db-ja.com

コライダーが互いに通過するのを防ぐ方法は?

収容スペース内にゲームオブジェクトを保持するのに問題があります。エッジに到達すると、一時的なプッシュバックが発生しますが、壁を通り抜けます。

プレーヤーでボックスコライダーを使用し、レベルの壁にメッシュコライダーを使用しています。プレイヤーキャラクター(宇宙船)の両方で、プレイヤーによって動きが制御されるという問題があります。そして、発射物であり、一定の速度での移動を忘れます。

これは、プレーヤーの私の移動コードです。 FixedUpdate()関数で実行されています。

//Movement
    haxis = Input.GetAxis("Horizontal") * speed;
    vaxis = Input.GetAxis("Vertical") * speed;

    moveVector.x = haxis;
    moveVector.z = vaxis;

    if(moveVector.magnitude > 1)
    {
        moveVector.Normalize();
    }

    rigidbody.MovePosition(transform.position + moveVector * speed);

弾丸を使用すると、弾丸に速度が与えられ、エンジンがムービーを計算します。彼らはBox Colliderを使用しており、物理学を持たないようにトリガーとして設定されています。しかし、OnTriggerEnterを使用してそれらを破棄します。

//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
    Destroy(gameObject);
}

メッシュコライダーの壁に衝突すると、すべてではありませんが一部の弾丸が破壊されます。プレーヤーは時々それを打って停止しますが、通常はそれを押し通すことができます。メッシュコライダーとのコリジョンを毎回機能させるにはどうすればよいですか?

16
Chris

動きの速いオブジェクトとの衝突は常に問題です。すべての衝突を確実に検出する良い方法は、物理シミュレーションに頼る代わりにレイキャスティングを使用することです。これは、弾丸や小さなオブジェクトに対してはうまく機能しますが、大きなオブジェクトに対しては良い結果を生み出しません。 http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html

擬似コード(ここにはコード補完がなく、メモリが不足しています):

void FixedUpdate()
{
    Vector3 direction = new Vector3(transform.position - lastPosition);
    Ray ray = new Ray(lastPosition, direction);
    RaycastHit hit;
    if (Physics.Raycast(ray, hit, direction.magnitude))
    {
        // Do something if hit
    }

    this.lastPosition = transform.position;
}
11
Petrucio

ピンボールのプロトタイプもあり、同じ分野で多くのトラブルを引き起こしました。これらは、これらの問題をほぼ(まだ完全には解決していませんが)解決するために行ったすべての手順です。

高速で移動するオブジェクトの場合:

  • リジッドボディの補間を「補間」に設定します(これは実際の物理シミュレーションには影響しませんが、オブジェクトのレンダリングを適切に更新します-これはプレーヤーやピンボールなどのレンダリングの観点から重要なオブジェクトでのみ使用しますが、発射体用)

  • 衝突検出を連続動的に設定します

  • スクリプトDontGoThroughThings( https://www.auto.tuwien.ac.at/wordpress/?p=26 )をオブジェクトに添付します。このスクリプトは、他の回答で投稿したレイキャスティングソリューションを巧みに使用して、問題のあるオブジェクトをコリジョンポイントの前に引き戻します。

編集->プロジェクト設定->物理

  • ペナルティの最小侵入を非常に低い値に設定します。私は0.001に設定しました

  • ソルバーの反復カウントをより高い値に設定します。私は50に設定しましたが、おそらくそれよりはるかに少ない数で大丈夫です。

パフォーマンスにペナルティが課せられることはすべてありますが、それは避けられません。デフォルト値はパフォーマンス上はソフトですが、小さくて動きの速いオブジェクトを適切にシミュレーションするためのものではありません。

12
Petrucio

剛体の衝突検出をContinuousまたはContinuous Dynamicに設定するのはどうですか?

http://unity3d.com/support/documentation/Components/class-Rigidbody.html

6
Chchwy
  • 編集--->プロジェクト設定--->時間...「固定タイムステップ」値を減らします。これにより問題は解決しますが、パフォーマンスに悪影響を与える可能性があります。

  • 別の解決策は、座標を計算することです(たとえば、ボールと壁があります。ボールは壁に当たります。したがって、壁の座標を計算し、これらの座標に従って打撃プロセスを設定します)。

1
fmp

そのため、メッシュコライダーを機能させることができませんでした。単純なボックスコライダーを使用して複合コライダーを作成しましたが、期待どおりに機能しました。

単純なMesh Colliderを使用した他のテストも同様です。

最善の答えは、単純なボックス/球体コライダーから複合コライダーを構築することであるように見えます。

私の特定のケースでは、パイプ型複合コライダーを作成するWizardを作成しました。

@script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
    public var outterRadius : float = 200;
    public var innerRadius : float = 190;
    public var sections : int = 12;
    public var height : float = 20;

    @MenuItem("GameObject/Colliders/Create Pipe Collider")
    static function CreateWizard()
    {
        ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
    }

    public function OnWizardUpdate() {
        helpString = "Creates a Pipe Collider";
    }

    public function OnWizardCreate() {
        var theta : float = 360f / sections;
        var width : float = outterRadius - innerRadius;

        var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);

        var container : GameObject = new GameObject("Pipe Collider");
        var section : GameObject;
        var sectionCollider : GameObject;
        var boxCollider : BoxCollider;

        for(var i = 0; i < sections; i++)
        {
            section = new GameObject("Section " + (i + 1));

            sectionCollider = new GameObject("SectionCollider " + (i + 1));
            section.transform.parent = container.transform;
            sectionCollider.transform.parent = section.transform;

            section.transform.localPosition = Vector3.zero;
            section.transform.localRotation.eulerAngles.y = i * theta;

            boxCollider = sectionCollider.AddComponent.<BoxCollider>();
            boxCollider.center = Vector3.zero;
            boxCollider.size = new Vector3(width, height, sectionLength);

            sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
        }
    }
}
1
Chris

古い質問ですが、多分それは誰かを助けます。

[プロジェクト設定]> [時間]に移動し、固定タイムステップと最大許容タイムステップを2または4で割ってみてください。

私は、プレイヤーがプレイヤーコライダーよりも小さな開口部を絞ることができ、それを解決できるという問題がありました。また、高速で移動するオブジェクトの停止にも役立ちます。

1
Timanious

1.)メッシュコリダーを使用しないでください。ボックスとカプセルコライダーの組み合わせを使用します。

2.)RigidBodyで制約を確認します。 Freeze Position Xにチェックマークを付けると、X軸上のオブジェクトを通過します。 (y軸と同じ)。

0
Simran Singh