10

オブジェクトをボックスにドラッグ アンド ドロップするゲームを開発していますが、オブジェクトがボックス内にあるかどうかを検出するための最良かつ最も効率的な方法がわかりません。

私はコライダーをよく知っており、BoxColliders とトリガーを使用して、オブジェクトがボックスに触れているかどうかを確認していますが、オブジェクトがボックスに触れている瞬間を検出したいと考えています (簡単にするために球であると想定できますが、後でメッシュである) は完全に私のボックス トリガー/コライダーの中にあります。

コライダーの「含む」方法について読みましたが、IIRCはそのコライダー内の1つのポイントをチェックするだけですが、オブジェクト全体がコライダー内にあるかどうかを知りたいです。

よろしくお願いします。

4

9 に答える 9

2

Short answer: If you want 100% accuracy, your algorithm will never be better than O(|V|) (worst case) where V = {all vertices in mesh}, meaning you'd run .Collides() over every vertex and break if you find one that is outside your container.

Longer answer: Several methods exist to subdivide mesh surfaces, examples include: KD-Trees, OcTrees. These are beyond the scope of an SO answer to provide a full implementation, I suggest you see the wiki pages for details.

You could use these methods to divide your mesh up in to smaller sets of vertices. To speed up your algorithm you would start at the root of your subdivision tree and test if that node is contained in your container box. Keep working through the tree until you find a node that is not contained by your box. This will allow your "contains" test to fail faster but ultimately you'll wind up testing every vertex if your box contains your mesh.

Caveat: This solution does not work if your mesh is animated. In that case your best bet is to use the bounds around things like arms, feet, legs, etc and use that information to cull your Contains() tests. Again, you'll end up having to test every vertex if the mesh is fully inside your box.

于 2012-10-30T13:56:56.700 に答える
2

ここに画像の説明を入力

すべてのボックスには boxCollider があります。オブジェクトが 2 番目のボックスに触れる場合、そのオブジェクトは最初のボックス内にある必要があります。

これは良い解決策ではありませんが、役に立つかもしれません。

于 2013-07-23T14:30:02.630 に答える
1

Renderer.boundsプロパティを使用して、オブジェクトのバウンディング ボックスを取得します。

あなたが持っているオブジェクトと、それがコライダー内にあることをどれだけ正確にチェックしたいかによっては、それを決定する簡単な方法の1つを使用するよりも.

于 2012-10-28T01:42:24.900 に答える
1

上記のボックス ソリューション内のボックスは適切なオプションですが、(さまざまなサイズ/形状のオブジェクトが原因で) それが機能しない場合は、 Physics.Raycastまたは Collider.Raycastを使用して何かを達成できる可能性があります。同様の問題があり、任意のポイントがコライダー内に含まれているかどうかをテストする必要がありました (その多くは、異常なぼんやりとした凹型オブジェクトでした)。

基本的なアイデアは、複数の方向からポイントに向かって光線を投射する「釘のベッド」アプローチです。すべてのレイで外側のコライダーをヒットした場合、ポイントがコライダーの内側に含まれていることをかなり確信で​​きます (ただし、完全には確実ではありません)。ここに写真があります:

レイキャストが含まれています

この図では、青い点が黄色のコライダーの内側にあるかどうかを確認しようとしています。緑色の矢印は成功したレイキャスト (黄色のコライダーにヒット) を表し、ピンクの矢印は失敗した (黄色のコライダーにヒットしない) ことを表します。

これを示すコード スニペットを次に示します。

public static class CollisionUtils {

    private static readonly Vector3[] raycastDirections;

    // These are the directions that we shoot rays from to check the collider.
    static UltrasoundCollisionUtils() {
        raycastDirections = new Vector3[5];
        raycastDirections[0] = new Vector3(0,1,0);
        raycastDirections[1] = new Vector3(0,-1,-0);
        raycastDirections[2] = new Vector3(0,0,1);
        raycastDirections[3] = new Vector3(-1.41f, 0, -0.5f);
        raycastDirections[4] = new Vector3(1.41f, 0, -0.5f);
    }

    public static bool IsContained (Vector3 targetPoint, Collider collider) {
        // A quick check - if the bounds doesn't contain targetPoint, then it definitely can't be contained in the collider

        if (!collider.bounds.Contains(targetPoint)) {
            return false;
        }

        // The "100f * direction" is a magic number so that we 
        // start far enough from the point.
        foreach (Vector3 direction in raycastDirections) {
            Ray ray = new Ray(targetPoint - 100f * direction, direction);

            RaycastHit dummyHit = new RaycastHit();
            // dummyHit because collider.Raycast requires a RaycastHit
            if (!collider.Raycast(ray, out dummyHit, 100f)) {
                return false;
            }
        }

        return true;
    }
}

このアルゴリズムを適応させる 1 つの方法は、Collider.Raycast を使用するのではなく、Physics.Raycast を実行することです。光線がコライダー以外のものに当たった場合、ターゲット オブジェクトが完全にコライダーに収まっていないことがわかります。

于 2014-02-06T05:22:31.777 に答える
1

より洗練されたクリーンなアプローチのために。これはあなたがしていることに最適です。ドラッグしているオブジェクトとボックスの間の距離を確認できます。

ボックスには、空間内の位置を表す ax、y、z 値があります。

したがって、ゲームオブジェクトをドラッグすると、ボックスの中心から x、y、または z 方向に 0.2 だけ離れている可能性があります。このメソッドを使用して、ドラッグしたオブジェクトとボックスの間の距離を計算してください。

    var other :Transform;
    function Update()
    {
        var dist = Vector3.Distance(other.position, transform.position);

    // while dragging 
    if(dist <10)// 10 being on all 3 axiz .
    {
    //dragged object.position = box position
    }

if (dist == 0)
{
print("i am in the centre of the box");
}

}

したがって、ゲームオブジェクトはボックスになります。

于 2013-10-28T22:16:49.347 に答える
0

テストしているオブジェクト全体を囲むBoxColliderを追加し、その境界の最小値と最大値がBoxColliderの入力に含まれていることを確認します...これは複雑なメッシュオブジェクトには適さない場合がありますが、それを回避できる場合があります。その安い

于 2013-02-04T13:06:52.863 に答える
0

簡単に言うと、コンテナの下部にボックス コライダーを配置することができます。球体またはその他のオブジェクトがそれに触れると、完全にコンテナ内に入ります。

于 2013-07-06T12:03:23.053 に答える
0

ただし、1つの方法があります....それほど正確ではありませんが、機能します:

  1. 車の四輪のようにコライダー(Circle / Box)で4つの空を作り、コライダーでこれらの空オブジェクトの親オブジェクトを作ります。
  2. 次に、触れられているかどうかに関係なく、すべてのコライダにブール値を割り当てます....
  3. 実際のメッシュコライダーと一緒に触れたコライダーの数を数えます...重なりの方向を大まかに推定します。2 の場合は、横から触れた、または重なったことを意味します。例:2つのコライダー+メッシュコライダーが衝突している場合、つまり横に重なっています...
于 2020-10-09T18:59:16.437 に答える