3

box2das3b2ContactListenerクラスに問題があります。b2ContactListenerを拡張し、PostSolveメソッドをオーバーライドするContactListenerという名前のクラスがあります。PostSolveは、2つのパラメーターを取ります。1つは、接触している2つのオブジェクトに関する情報を保持するcontact、もう1つは、接触に関する情報を保持するインパルスです。インパルスパラメータを使用して、2つのオブジェクトがどれだけ強く当たるかを決定し、それに応じてダメージを適用します。

問題は次のとおりです。円形のものを作成し、それを地面として持っている静止体上でゆっくりと転がしてから、かなり大きなオブジェクトを地面の任意の場所にドロップすると、移動中の円が接触します。ただ転がるだけで大​​きくなる衝動。これにより、回転する円形のオブジェクトが壊れてはいけないときに壊れます。

まるで静止した体を揺さぶり、数百メートル離れた物体に甚大な被害を与えるかのようですが、それは円にのみ影響します。

誰かが状況に光を当てることができますか?これは既知の問題ですか?回避策?

Box2DAs3バージョン2.1aを使用しています。

更新:体が多くのダメージを与えるこの奇妙な状態に入ると、それに触れる円は大量の大きな衝動を受け取ります。円形でないものが体に接触すると、問題はなくなります。また、この問題は静的オブジェクトだけでなく、動的および運動学的にも発生します。

アップデート:問題をさらに絞り込みました。大きなオブジェクトの平らなエッジが私の地面のオブジェクトに当たると、コンタクトリスナーはびっくりして、の質量インパルスを適用します。円だけでなく、目覚めていて地面に接触しているオブジェクトは、大量のPostSolveメソッド呼び出しを受け取ります。円が地面を転がっている間に、11ピクセル×11ピクセルのサイズの箱を地面に落としてみました。バグは発生しませんでした。ただし、ボックスが12 x 12の場合、バグは発生します。また、12×12〜0.1度の大きさの箱を回転させてもバグは発生しません。再現するには、十分な大きさの接触領域が必要です。また、ボックスの密度は何にも影響しません。また、ボックスが幅10、高さ100の長方形である場合、バグが再現されます。オブジェクトのサイズがバグを引き起こしているようですが、

更新:これは、私が作成したBox2Dフォーラムの投稿へのリンクです。ソース付きのswfの例があります。

リンク

4

1 に答える 1

0

おお。だから私はついに問題が何であるかを見つけました。

ContactListenerで何か凝ったことをして回避策があるかどうかを何時間も試した後、PostSolveメソッドがどこから呼び出されているかを確認することにしました。これはb2Islandという名前のクラスに由来し、そのクラスのReport関数に由来します。一見、問題を簡単に見つけました。彼女は機能です:

private static var s_impulse:b2ContactImpulse = new b2ContactImpulse();
public function Report(constraints:Vector.<b2ContactConstraint>) : void
{
    if (m_listener == null)
    {
        return;
    }

    for (var i:int = 0; i < m_contactCount; ++i)
    {
        var c:b2Contact = m_contacts[i];
        var cc:b2ContactConstraint = constraints[ i ];

        for (var j:int = 0; j < cc.pointCount; ++j)
        {
            s_impulse.normalImpulses[j] = cc.points[j].normalImpulse;
            s_impulse.tangentImpulses[j] = cc.points[j].tangentImpulse;
        }
        m_listener.PostSolve(c, s_impulse);
    }
}

つまり、明らかにs_impulse varは静的であるため、b2Islandクラスのすべてのインスタンスで同じになり(複数ある場合)、どの時点でもリセットされません。s_impulse varへのすべての参照は上に表示されているため、他に何も起こりません。ただし、ここで重要なのは、円にはポリゴンとの接触が1つしかないため、報告時に1つの接触のインパルスのみが設定されるということです。他の連絡先は、リセットされていない場合、報告される最後のオブジェクトの最後のインパルスを持ちます。

基本的に、円に見ら​​れる衝動は、実際に報告されたばかりのものからの衝動に残されています。これを修正するには、次のようにします。

private static var s_impulse:b2ContactImpulse = new b2ContactImpulse();
public function Report(constraints:Vector.<b2ContactConstraint>) : void
{
    if (m_listener == null)
    {
        return;
    }

    for (var i:int = 0; i < m_contactCount; ++i)
    {
        s_impulse = new b2ContactImpulse();

        var c:b2Contact = m_contacts[i];
        var cc:b2ContactConstraint = constraints[ i ];

        for (var j:int = 0; j < cc.pointCount; ++j)
        {
            s_impulse.normalImpulses[j] = cc.points[j].normalImpulse;
            s_impulse.tangentImpulses[j] = cc.points[j].tangentImpulse;
        }
        m_listener.PostSolve(c, s_impulse);
    }
}

それはそれと同じくらい簡単です。

于 2011-03-04T23:32:50.970 に答える