2017-01-20 3 views
-1

私は開発中のlibgdxミニゲームで致命的なエラーが再発しています。私が集めたものについては、body2dのネイティブエラーです。これの原因としては、タイムステップ中に人体が発生することが考えられますが、適切な対策を講じていると思います。LIbgdxでボディを作成すると、時々box2Dcrashが発生する

次のケースは似ていますが、実際にはアレイをループしている間にオブジェクトを取り除くことについてのものでした:Deleting and creating body in libGDX。私自身の問題について

、ここでのクラッシュの出力は次のとおりです。

<コンソール>

EntityManager: entity generation begin --------- 
IceSpike: generating physics 
IceSpike: generated physics 
IceSpike: generating graphics 
EntityManager: entity generation registered 
IceSpike: generating physics 
IceSpike: generated physics 
IceSpike: generating graphics 
EntityManager: entity generation registered 
IceSpike: generating physics 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000066bcbd0d, pid=5288, tid=0x00000000000013d4 
# 
# JRE version: Java(TM) SE Runtime Environment (8.0_111-b14) (build 1.8.0_111-b14) 
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.111-b14 mixed mode windows-amd64 compressed oops) 
# Problematic frame: 
# C [gdx-box2d64.dll+0xbd0d] 
# 
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows 
# 
# An error report file with more information is saved as: 
# D:\Codage\projects\eclipse\git\spacegame\SpaceGame\android\assets\hs_err_pid5288.log 
# 
# If you would like to submit a bug report, please visit: 
# http://bugreport.java.com/bugreport/crash.jsp 
# The crash happened outside the Java Virtual Machine in native code. 
# See problematic frame for where to report the bug. 
# 
AL lib: (EE) alc_cleanup: 1 device not closed 

ログファイル:http://pastebin.com/JjBGnTri

それがコードに来るとき、私がしようとしますできるだけシンプルにする。うまくいけば、私は問題の一部を切り詰めていません。

私はエンティティの生成と破壊を処理するEntityManagerを持っています。ゲームのすべてのエンティティはエンティティ(大きな抽象的なブロブ)を継承します。それらはすべてgeneratePhysics(World physics)で生成されたbox2d本体を持っています。

のEntityManager

private GameWorld world; 
private Array<Entity> generation; 
private Array<Entity> generationCpy; 
private Array<Entity> trash; 
private Array<Entity> trashCpy; 

public void update(float delta) 
{ 
    //generate new entities 
    Gdx.app.debug(this.getClass().getSimpleName(), "entity generation begins ---------"); 
    if(generation.size != 0) 
    { 
     generationCpy = new Array<Entity>(generation); 
     for (Entity entity : generationCpy) 
     { 
      entity.generate(world.getPhysics(),world.getAssetManager()); 
     } 
    } 

    //destroy old entities 
    Gdx.app.debug(this.getClass().getSimpleName(), "entity destruction begins ---------"); 
    if(trash.size != 0) 
    { 
     trashCpy = new Array<Entity>(trash); 
     for(Entity entity : trashCpy) 
     { 
      trash.removeValue(entity, true); 
      entity.destroy(world.getPhysics()); 
      entity = null; 
     } 
    } 
    Gdx.app.debug(this.getClass().getSimpleName(), "entity generation complete ------"); 

エンティティ

public final void generate(World physics, AssetManager assetManager) 
{ 
    if(state != EntityState.GENERATED) 
    { 
     generatePhysics(physics); 
     generateGraphics(assetManager); 
     setState(EntityState.GENERATED); 
    } 
    else 
     Gdx.app.error(this.getClass().getSimpleName(), "entity couldn't be generated. It had allready been generated"); 
} 

はこれまでのところ、唯一のスパイクが懸念されているように見える、と時間のほとんどは、すべてがスムーズに実行されます。残りの時間は、これがクラッシュ一部です:

IceSpikes

@Override 
public void generatePhysics(World physics) 
{ 
    Gdx.app.debug(this.getClass().getSimpleName(), "generating physics"); 

    BodyDef bodyDef = new BodyDef(); 
    bodyDef.type = BodyType.DynamicBody; 
    bodyDef.position.set(this.position.cpy().scl(1/PPM)); 

    body = physics.createBody(bodyDef); 
    body.setBullet(true); 

    PolygonShape shape = new PolygonShape(); 
    Vector2 vertices[] = new Vector2[3]; 
    vertices[0] = new Vector2(-width/2,-height/2).scl(1f/PPM); 
    vertices[1] = new Vector2(0,height/2).scl(1f/PPM); 
    vertices[2] = new Vector2(width/2,-height/2).scl(1f/PPM); 
    shape.set(vertices);   

    FixtureDef fixtureDef = new FixtureDef(); 
    fixtureDef.shape = shape; 
    fixtureDef.density = 1f; 
    fixtureDef.restitution = 1f; 
    fixtureDef.filter.categoryBits = CollisionManager.BIT_PROJECTILE; 
    fixtureDef.filter.maskBits = CollisionManager.BIT_PLAYER; 

    Fixture fixture = body.createFixture(fixtureDef); 
    fixture.setUserData(this); 

    shape.dispose(); 

    Gdx.app.debug(this.getClass().getSimpleName(), "generated physics"); 
} 

これは、それが((world.stepで衝突した後である、IceSpikesのタイミングの作成によるものであることを示唆しています) )。しかし、これは私のエンティティ管理システム全体のポイントです。出力によって確認されたように、world.step()の外側にあるボディを生成/削除します。

また、複製されている間にエンティティが世代とゴミ箱の配列から削除されないように、コピーされた配列が設定されています。

私は何か見落とされているに違いないが、何?そこから進んでいく方法は?

+0

これが投票されたのはなぜですか?私は新しく、私は少なくとも理由を知っているので、次回は自分の投稿を改善することができます... – MeMeek

+0

libgdxフォーラムの誰かが、これが '.scl(1f/PPM)'の誤用のために来るかもしれないと言いました。体が小さすぎて爆発するであろう。しかし、私はそれらをもう少し拡大しようとしましたが、私はまだ問題があります。私はまだ調査中です。 – MeMeek

答えて

0

問題は、同じボディが複数作成された/破壊されたことが原因であることが判明しました。これは、エンティティマネージャで複数の参照が原因で発生しました。エンティティ管理システムはリスナーに基づいています。すべてのエンティティはenum EntityStateを持ち、エンティティマネージャは状態が変化したときに通知を受けます。私はこの状態がコードの残りの部分で一度だけ変化していることを確実にしていると思っていましたが、判明したように、それはしませんでした。

単純な修正はif(this.state != state)という条件を追加することでした。

ここでそれが今のように見える方法は次のとおりです。

public final void setState(EntityState state) 
{ 
    if(this.state == state) 
     Gdx.app.error(this.getClass().getSimpleName(), "the state was allready " + state); 
    else 
    { 
     this.state = state; 
     switch(state) 
     { 
      case CREATED:  notifyCreation(this);  break; 
      case GENERATED:  notifyGeneration(this);  break; 
      case TO_BE_REMOVED: notifyFlagForRemoval(this); break; 
      case INACTIVE:  notifyDestruction(this); break; 
      default : Gdx.app.error(this.getClass().getSimpleName(), "entity state became " + state); 
     } 
    } 
} 

私は出回っ体が前にヌルだったかどうかをチェックする他のものの間のような特定の対策を取っていたので、しかし、「なぜ」まだ、私にビットを見逃さそれを破壊する:

protected final void destroyBody(World physics) 
{ 
    Gdx.app.debug(this.getClass().getSimpleName(), "destroying body"); 
    if(body != null) 
    { 
    final Array<JointEdge> joints = body.getJointList(); 
    while (joints.size > 0) 
    { 
     Gdx.app.log("GameWorld", "destroying joint"); 
     Joint joint = joints.get(0).joint; 
     physics.destroyJoint(joint); 
     joints.removeIndex(0); 
    } 
    physics.destroyBody(body); 
    } 
    else 
    { 
    Gdx.app.error(this.getClass().getSimpleName(), "entity's body not found. No action taken."); 
    } 

}

限り私が懸念していますように、これは修正プログラムは私の場合に非常に固有のものであり、私にはややハック感じていても、固定されています。

0

エンティティ(基本的に物理コンポーネントを持つ)の作成と削除はロックでバインドする必要があります。

物理ワールドがロックされていない場合は、作成と削除を実行する必要があります。

private World physicsWorld; 
private PhysicsSystem physicsSystem; 

@Override 
protected void initialize() { 

    physicsWorld =physicsSystem.getPhysicsWorld(); 
} 

@Override 
protected void processSystem() { 

    if(!physicsWorld.isLocked()) { 
      removeBodyFromWorld();  
      addBodyIntoWorld(); 
    } 
} 

removeBodyFromWorldメソッドでは、必要なエンティティを削除してaddBodyIntoWorldメソッドで新しいボディを作成します。

うまくいけば助かります。
おかげであなたはここに掲載のコードから、何かを見落としたかどうかについては

+0

あなたの答えをありがとう。私はすでに私が物理世界の舞台にいないことを確認しています。エンティティの生成と削除のために、if(!world.getPhysics()。isLocked())という条件を断ちましたが、その問題は残っています。それでも、私はあなたを 'isLocked()'メソッドに紹介してくれてうれしいです。これは将来的には非常に便利になるかもしれません。 – MeMeek

0

は、あなたが(generatePhysics方法で)verticesに関してshapeを見落とし。

これらの頂点(または他の頂点)を使用するよう指示されたポリゴンはありません。ただし、ポリゴンを使用するフィクスチャを作成する前に、3つ以上の頂点を設定する必要があります。

+0

ああ、ありがとう。エンティティ生成登録メッセージを出力するコードはどうですか?私はそれを見ていないし、またその論理を見たいと思っている。 –

+0

私のエンティティ管理システムのものです。これはEntityStateに基づいています。 EntityManagerは状態の変更をリッスンし、エンティティを世代配列、特定の配列(発射物/小惑星/集団...)またはゴミ箱に配置します。私はその問題が本当にそこから来る可能性が高いと思うようになりました。現時点では(私が現在やっている)私のところからより多くの調査が必要なので、投稿は「保留中」だと思います。 – MeMeek

関連する問題