IsLockedアサーションエラーを発生させずに、接触時にBox2Dボディを破棄するにはどうすればよいですか?


7

ボディを世界から削除しようとすると、このエラーが発生します。

java:/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp:134:void b2World :: DestroyBody(b2Body *):Assertion 'IsLocked()== false'失敗した。

何が悪いのですか?


3
実際にそのエラーを読みましたか?
o0 '。

回答:


22

libgdxでのbox2dの私の小さな経験から、最新のポートによってのみ悪化した例外を含む問題を分離して解決することが難しい場合があります。2.2.1より前のバージョンでは、発生しているような同期の問題がなくてもボディを簡単に削除できましたが、2.2.1をサポートするlibgdxビルドに移行した後、同じ問題が発生し始めました。いくつかの人から提案された私の回避策は、世界がシミュレーションされている間は、世界から体を削除できないことでした。

世界が踏まれているときに、あなたが世界から肉体を取り除こうとしている可能性はありますか?基本的に、これを行おうとすると、box2dは気に入らないので、実行する必要があるのはの外側のボディを削除することですworld.step。私が行ったのは、world.stepメソッドの外部で.userDataチェックされるbool isFlaggedForDeleteを使用して、ボディのユーティリティクラスを追加したことです。

public void sweepDeadBodies() {
   for (Iterator<Body> iter = CURRENT_WORLD.getBodies(); iter.hasNext();) {
     Body body = iter.next();
     if(body!=null) {
          YourCustomUserData data = (YourCustomUserData) body.getUserData();
          if(data.isFlaggedForDelete) {
          CURRENT_WORLD.destroyBody(body);
            body.setUserData(null);
            body = null;
          }
     }
}

world.stepの直後にこのようなものを実行すれば、動作するはずです。ボディを破棄しようとしているコードでは、.isFlaggedForDeleteをtrueに設定するだけで、次のworld.stepの前に削除されます。


2
多くのボディを含むワールドの場合、sweepDeadBodiesここで提案する方法は、削除されないボディを反復する多くのサイクルを無駄にします。このような場合には、上から、破壊される体へのポインタをプッシュ検討deadBodiesを通して繰り返し、その後、外側のスコープ内のリストことの後stepに行われると、それをクリアします。
あんこ

5

だから私たちはあなたのエラーがあります:

/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp:134:void b2World :: DestroyBody(b2Body *):Assertion 'IsLocked()== false'が失敗しました。

分解してみましょう:

このエラーの最初の部分のほとんどは、エラーが発生している場所を示すのに役立つ指示です。

/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/Dynamics/b2World.cpp

表示されているディレクトリ構造内のb2World.cppと呼ばれるソースファイルにエラーが生成されているようです。そしてそれは起こっています:

:134:

134行目。

そうすると、

void b2World :: DestroyBody(b2Body *):

voidaへのポインタを返し、受け入れる関数b2World:DestroyBody()がb2Bodyエラーを報告しています。

これでエラーの「どこ」の部分が終了しましたが、今は「何」かを示しています。それは等しいと主張しようとしているように見えますisLocked()false

アサーション「IsLocked()== false」が失敗しました。

しかし、それは失敗しています。

今はBox2Dを使用したことがありませんが、破壊しようとしているボディがロックされていることを意味していると思います。ボディがロックされている理由と、ロックを解除する方法を理解する必要があります。


4

Libgdxの実装はネイティブバージョンへのブリッジにすぎないため、すべて同じルールが適用されます。

シミュレーションの実行中は、ボディ/フィクスチャー/ジョイントを削除しないでください。

ボディ/フィクスチャー/ジョイントを2回以上外そうとしないでください。

ボディを削除するときに、フィクスチャーまたはジョイントへのポインター(参照)を残さないでください。

余分な注意を払うために-多分少し妄想さえ-私は私の体を取り除くためにこの方法を使います:

/**
 * Safe way to remove body from the world. Remember that you cannot have any
 * references to this body after calling this
 *
 * @param body
 *            that will be removed from the physic world
 */

public static void removeBodySafely(Body body) {
    //to prevent some obscure c assertion that happened randomly once in a blue moon
    final ArrayList<JointEdge> list = body.getJointList();
    while (list.size() > 0) {
        world.destroyJoint(list.get(0).joint);
    }
    // actual remove
    world.destroyBody(body);
}

2

これが最良の方法です。Box2Dのマニュアルを読んでください。CURRENT_WORLD.step(..、...、...);の直後にこれを呼び出す必要があります。

Iterator<Body> i = CURRENT_WORLD.getBodies();
Body node=i.next();
while (i.hasNext()) {
    Body oBj=node;
    node=i.next();
    YourCustomUserData data = (YourCustomUserData) oBj.getUserData();
    if(data!=null &&  data.isFlaggedForDelete){
        CURRENT_WORLD.destroyBody(oBj);             
    }
}

はい....うまく
いき

0

エラーはそれをすべて言います、あなたはあなたが体を削除したい瞬間に世界がロックされているかどうかを確認する必要があります

if(!world.isLocked())
     world.destroyBody(body)

それは私のために働いた:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.