2017-01-20 1 views
-1

내가 개발하고있는 libgdx 미니 게임에서 재발하는 "임의"치명적인 오류가 발생했습니다. 내가 수집 한 것에 대해, body2d 네이티브 에러이다. 바디 생성과 관련있다. 가능한 원인은 타임 스텝 (timestep) 동안 시체가 생성되는 것입니다. 그러나 나는 적절한 대응 조치를 취했다고 믿습니다.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

내 entityManager에서 mutiple 참조로 인해 같은 본문이 여러 번 생성/삭제되어이 문제가 발생하는 것으로 나타났습니다. 내 엔티티 관리 시스템은 리스너를 기반으로합니다. 모든 엔티티는 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); 
     } 
    } 
} 

은 "왜"나는 allready 몸이 전에 null의 경우 확인 다른 것들 사이처럼, 특정 카운터 조치를 복용했기 때문에 아직도 나에게 조금 회피한다 그것을 파괴 :

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

관련 문제