回答:
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の前に削除されます。
sweepDeadBodies
ここで提案する方法は、削除されないボディを反復する多くのサイクルを無駄にします。このような場合には、上から、破壊される体へのポインタをプッシュ検討deadBodies
を通して繰り返し、その後、外側のスコープ内のリストことの後step
に行われると、それをクリアします。
だから私たちはあなたのエラーがあります:
/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 *):
void
aへのポインタを返し、受け入れる関数b2World:DestroyBody()がb2Body
エラーを報告しています。
これでエラーの「どこ」の部分が終了しましたが、今は「何」かを示しています。それは等しいと主張しようとしているように見えますisLocked()
false
アサーション「IsLocked()== false」が失敗しました。
しかし、それは失敗しています。
今はBox2Dを使用したことがありませんが、破壊しようとしているボディがロックされていることを意味していると思います。ボディがロックされている理由と、ロックを解除する方法を理解する必要があります。
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);
}
これが最良の方法です。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);
}
}