2017-01-20 23 views
-1

我在開發中的libgdx迷你遊戲中出現了一個經常性的「隨機」致命錯誤。對於我所蒐集的內容,這是一個與機體創建有關的box2d原生錯誤。造成這種情況的一個可能原因是在一個時間步中產生一個身體,但我相信我採取了適當的對策。爲什麼我在創建LIbgdx中的物體時有時會出現box2Dragsh

以下情況看起來很相似,但實際上是關於從數組中刪除對象的同時通過它循環的: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。遊戲中的所有實體都從Entity(一個大的抽象blob)繼承而來。它們都有一個box2d主體,它在generatePhysics(World physics)中生成。

的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"); 
} 

這表明它是由於定時創建IceSpikes的,這是一個碰撞之後(在world.step() )。但是,這正是我整個實體管理體系的重點。它生成/移除world.step()之外的物體,如輸出所證實的那樣。

此外,複製數組的設置是爲了防止實體在循環播放時從生成和垃圾數組中刪除。

我一定忽略了一些東西,但是什麼?任何想法如何從那裏開始?

+0

爲什麼這個否決?我是新的,我至少知道爲什麼,所以我可以提高我的帖子下一次...... – MeMeek

+0

有人在libgdx論壇上說,這可能到來的'.scl僞的missusage(1F/PPM)'導致太小的物體會爆炸。但是,我試圖擴大一點,我仍然有這個問題。我仍在調查。 – MeMeek

回答

0

問題竟然是由同一機構的多個創作/銷燬,引起了我的EntityManager多發性引用造成的。我的實體管理系統基於聽衆。每個實體都有一個枚舉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); 
     } 
    } 
} 

但是,「爲什麼」仍然逃避我了一下,因爲我是allready採取一定的反制措施,如除其他事項外檢查,如果身體之前爲空摧毀:

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

謝謝你的回答。恐怕我已經確定我不在物理世界的一步。我jadded一個條件,如果(!world.getPhysics()。isLocked())'爲實體的產生和清除,只是要確定,但問題依然存在'。不過,我很高興你向我介紹了'isLocked()'方法。這可能在未來變得非常方便。 – MeMeek

0

,你是否已經忽略了什麼,從這裏發佈的代碼,你與問候忽視shapevertices(在generatePhysics方法)。

無處是指示使用這些頂點(或任何其它頂點)的多邊形。在創建將使用多邊形的燈具之前,必須先設置3個或更多頂點。

+0

啊,謝謝。輸出「實體代註冊」消息的代碼如何?我沒有看到它,也想檢查它的邏輯。 –

+0

來自我的實體管理系統。它基於一個EntityState。 EntityManager偵聽狀態變化,並將這些實體放入一個生成數組,一個特定數組(射彈/小行星/可收集...)或垃圾桶中。我認爲這個問題確實更可能來自那裏。現在我需要更多的調查(我現在正在做這個),所以我猜這個帖子是「擱置」的。 – MeMeek

相關問題