Làm cách nào để phá hủy phần thân Box2D khi tiếp xúc mà không gặp lỗi xác nhận IsLocked?


7

Tôi gặp lỗi này khi cố gắng loại bỏ một cơ thể khỏi thế giới:

java: /var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/D Netherics / b2World.cpp: thất bại.

Tôi đang làm gì sai?


3
Bạn đã thực sự đọc lỗi đó?
o0 '.

Câu trả lời:


22

Từ kinh nghiệm nhỏ bé của tôi với box2d trong libgdx, đôi khi có thể khó tách biệt và giải quyết các vấn đề với các ngoại lệ chỉ bị làm xấu đi bởi cổng mới nhất. Trước 2.2.1, tôi có thể dễ dàng xóa các cơ quan khỏi thế giới mà không gặp sự cố đồng bộ hóa như bạn đang gặp phải nhưng sau khi chuyển sang bản dựng libgdx hỗ trợ 2.2.1, tôi bắt đầu thấy các vấn đề tương tự. Cách giải quyết đối với tôi, được một số người gợi ý là bạn không thể loại bỏ các thi thể khỏi thế giới trong khi thế giới có thể đang được mô phỏng.

Có khả năng bạn đang cố gắng loại bỏ một cơ thể khỏi thế giới khi thế giới đang được bước đi? Về cơ bản, nếu bạn cố gắng làm điều này, box2d không thích nó vì vậy những gì bạn phải làm là loại bỏ các cơ quan bên ngoài world.step. Những gì tôi đã làm đã được thêm một lớp tiện ích cho cơ thể .userDatavới một bool isFlaggedForDelete sẽ được kiểm tra bên ngoài phương thức world.step.

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;
          }
     }
}

Nếu bạn chạy một cái gì đó như thế này ngay sau world.step, nó sẽ hoạt động. Trong mã của bạn, nơi bạn đang cố gắng phá hủy cơ thể, chỉ cần đặt nó .isFlaggedForDelete thành true và nó sẽ bị xóa trước thế giới tiếp theo.


2
Đối với các thế giới chứa nhiều cơ thể, sweepDeadBodiesphương pháp được đề xuất ở đây sẽ lãng phí rất nhiều chu kỳ lặp qua các cơ thể sẽ không bị xóa. Trong các trường hợp như vậy, hãy xem xét việc đẩy các con trỏ tới các vật thể bị phá hủy vào một deadBodiesdanh sách ở phạm vi bên ngoài, sau đó lặp lại qua đó sau khi stepxóa nó một lần.
Anko

5

Vì vậy, chúng tôi có lỗi của bạn:

/var/lib/hudson/jobs/libgdx/workspace/trunk/gdx/jni/Box2D/D Netherics / b2World.cpp:

Hãy phá vỡ nó:

Hầu hết các phần đầu của lỗi này là chỉ đường hữu ích để cho bạn biết nơi các lỗi đang xảy ra.

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

Có vẻ như lỗi đang được tạo trong một tệp nguồn có tên b2World.cpp bên trong cấu trúc thư mục được hiển thị. Và nó đang diễn ra:

: 134:

Trên dòng 134.

Sau đó, nó trông giống như,

void b2World :: DestBody (b2Body *):

hàm b2World: DestBody () trả về voidvà chấp nhận một con trỏ tớib2Body đang báo cáo lỗi.

Điều đó đã hoàn thành phần "lỗi" ở đâu, bây giờ nó cho chúng ta biết "cái gì". Trông giống như nó đang cố gắng để khẳng định rằng isLocked()bằngfalse

Khẳng định `IsLocked () == false 'không thành công.

Nhưng nó thất bại.

Bây giờ tôi chưa bao giờ sử dụng Box2D, nhưng tôi đoán điều đó có nghĩa là cơ thể bạn đang cố gắng phá hủy đã bị khóa. Bạn sẽ cần phải tìm hiểu tại sao cơ thể bị khóa và cách mở khóa.


4

Việc triển khai Libgdx chỉ là cầu nối với phiên bản gốc nên tất cả các quy tắc tương tự đều được áp dụng.

Không bao giờ cố gắng loại bỏ một cơ thể / vật cố định / khớp khi mô phỏng đang chạy.

Không bao giờ cố gắng loại bỏ một cơ thể / vật cố định / khớp nhiều lần.

Không bao giờ để con trỏ (còn gọi là tài liệu tham khảo) vào đồ đạc hoặc khớp khi bạn xóa phần thân.

Để thận trọng hơn - thậm chí có thể hơi hoang tưởng - tôi sử dụng phương pháp này để loại bỏ cơ thể của mình:

/**
 * 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

Đây là cách tốt nhất để làm điều đó, tôi đọc nó trong hướng dẫn Box2D. Bạn phải gọi nó ngay sau 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);             
    }
}

vâng .... hoạt động rất tốt
Vishal Kumar

0

Lỗi nói lên tất cả, bạn cần kiểm tra xem thế giới có bị khóa trong khoảnh khắc mà bạn muốn loại bỏ cơ thể không

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

điều đó đã làm việc cho tôi :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.