Box2D-在运行时创建实体时,实体不会发生碰撞

Box2D - When creating a body at runtime, the body does not collide

本文关键字:实体 碰撞 运行时 创建 Box2D-      更新时间:2023-10-16

我一直在开发一款具有可破坏环境的游戏,我提出了一个解决方案,可以在我的ContactListener对象中检查可能的破坏。显然,因为这是在Step()中发生的,所以我将销毁处理推迟到步骤之后。我通过汇集需要在联系人侦听器中处理的"销毁事件"来实现这一点,然后在Step()之后立即调用类似contactListener->processDestructionEvents();的东西。

我这样做的方法是在beginContact事件中捕捉碰撞的固定装置,然后确定碰撞角度,然后使用该角度对固定装置本身进行光线投射。然后,我从夹具的b2PolygonShape抓取顶点,然后生成两个新的形状,根据光线的入射点和出射点进行分割。实体上的原始夹具将被销毁,然后为第一个新形状生成一个新夹具,并将其添加到原始实体中。对于第二个形状,将生成一个新实体,并将该形状添加到此新实体中。

不管怎样,一切都很好,在调试视图中,我可以看到新的形状已经生成,并且都在适当的位置。然而,在这一点上,我的行为真的很糟糕。一旦这个过程完成,原始物体和新生成的物体都不会与任何物体碰撞。如果我启用连续物理,有时动态对象会与这些物体/固定装置的某个边缘碰撞,但并不总是如此。我想知道我在运行时重建身体/固定装置的方法中是否做错了什么。以下是生成新对象的代码,如有任何帮助,将不胜感激。

void PhysicsContactListener::processDestructionEvents() {
   if(!hasDestructionEvents) {return;}
   for(destructionEventsIterator = destructionEvents.begin(); destructionEventsIterator != destructionEvents.end(); ++destructionEventsIterator) {
      b2Filter f1, f2;
      f1.groupIndex = destructionEventsIterator->originalFixture->GetFilterData().groupIndex;
      f1.categoryBits = destructionEventsIterator->originalFixture->GetFilterData().categoryBits;
      f1.maskBits = destructionEventsIterator->originalFixture->GetFilterData().maskBits;
      f2.groupIndex = destructionEventsIterator->originalFixture->GetFilterData().groupIndex;
      f2.categoryBits = destructionEventsIterator->originalFixture->GetFilterData().categoryBits;
      f2.maskBits = destructionEventsIterator->originalFixture->GetFilterData().maskBits;
      b2PolygonShape newShape0 = destructionEventsIterator->newFixtures[0];
      b2FixtureDef fixture0Def;
      fixture0Def.shape = &newShape0;
      fixture0Def.density = 1.0f;
      fixture0Def.restitution = 0.2f;
      b2Fixture* fixture1 = destructionEventsIterator->hostBody->CreateFixture(&fixture0Def);
      fixture1->SetFilterData(f1);
      //destructionEventsIterator->hostBody->SetAwake(true);
      destructionEventsIterator->hostBody->ResetMassData();
      //destructionEventsIterator->hostBody->SetActive(true);
      destructionEventsIterator->hostBody->SetTransform(destructionEventsIterator->hostBody->GetPosition(), destructionEventsIterator->hostBody->GetAngle());
      b2BodyDef bd;
      bd.position = destructionEventsIterator->hostBody->GetPosition();
      bd.angle = destructionEventsIterator->hostBody->GetAngle();
      bd.type = destructionEventsIterator->hostBody->GetType();
      b2Body* newBody = destructionEventsIterator->hostBody->GetWorld()->CreateBody(&bd);
      b2PolygonShape* newShape1 = (b2PolygonShape*)(&destructionEventsIterator->newFixtures[1]);
      b2Fixture* fixture2 = newBody->CreateFixture(newShape1, destructionEventsIterator->hostBodyDensity);
      fixture2->SetFilterData(f2);
      newBody->SetAngularVelocity(destructionEventsIterator->hostBody->GetAngularVelocity());
      newBody->SetLinearVelocity(destructionEventsIterator->hostBody->GetLinearVelocity());
      //newBody->SetAwake(true);
      newBody->ResetMassData();
      //newBody->SetActive(true);
      newBody->SetTransform(destructionEventsIterator->hostBody->GetPosition(), destructionEventsIterator->hostBody->GetAngle());
      destructionEventsIterator->hostBody->DestroyFixture(destructionEventsIterator->originalFixture);
   }

这两块不碰撞吗?看看每个夹具最终得到的categoryBits和maskBits值——看起来每个工件都有相同的值。我的猜测是,你只是忽略了这样一个事实,即这些掩码是通过两种方式相互检查的,例如来自Box2D源代码:

bool collide =
      (filterA.maskBits & filterB.categoryBits) != 0 &&
      (filterA.categoryBits & filterB.maskBits) != 0;

另一方面,如果你的意思是,这些碎片什么都没有碰撞,只是从地上掉下来,除了偶尔,永远掉下去,那么我可能会怀疑多边形缠绕不正确。

顺便说一句,b2Filter只包含基元,所以你可以直接分配它们:

b2Filter f1 = destructionEventsIterator->originalFixture->GetFilterData();

此外,第一个SetTransform和第二个ResetMassData是冗余的。