为Box2D实体设置父子关系

Parenting Box2D bodies

本文关键字:父子关系 设置 实体 Box2D      更新时间:2023-10-16

我在一起养育身体时遇到了一些问题。当我将多个固定装置连接到一个主体时,似乎会在内存管理中产生问题。这种情况发生在冲突期间,因此使用XCode时,我会收到以下错误消息:

 *** error for object 0xf572ef0: incorrect checksum for freed object - object was probably    modified after being freed.
 *** set a breakpoint in malloc_error_break to debug

当实体只有一个固定装置时,不会发生这种情况。

我试图实现的是,例如,如果一个角色拿起一个项目,则转换将成为父对象的子对象。所以,我们会得到:

 Parent_R + Child_R
 Parent_P + Child_P

由于我是在物理引擎的背景下,我认为有一种方法可以在对象之间创建父/子关系。我可以简单地将物体(比如之前掉落的物体)从物理世界中分离出来,并将其视为一个纯粹的精灵游戏物体。这涉及到相当多的来回(例如,当回到物理世界时,重新创建夹具/主体)。这是我的代码:

void GameObject::AttatchToBody(GameObject& obj1, GameObject& obj2, b2World& world)
{
    b2PolygonShape boxShape;
    boxShape.SetAsBox(obj2.width, obj2.height);
    b2FixtureDef boxFixtureDef;
    boxFixtureDef.restitution = 0.2f;
    boxFixtureDef.friction = 0.3f;
    boxFixtureDef.shape = &boxShape;
    boxFixtureDef.density = 1 / (obj2.width + obj2.height);
    obj2.fixture = obj1.body->CreateFixture(&boxFixtureDef);
    obj2.body = obj1.body;
}

非常感谢您的帮助!

除了身体/固定装置关系之外,我在Box2d中没有看到任何育儿关系。

在我看来,obj1和obj2引用了相同的Box2d内存分配对象(主体)。例如,当你删除obj1时,你可能会删除附加到它的主体(通过执行类似world->DestroyBody(…)的操作)。在下一次box2d更新中,你引用了一个你没有分配并被告知要销毁的对象(到box2d系统)。这可能是问题所在吗?

我还看到您正在obj2和obj1之间共享一个fixture。当obj1被box2d系统回收(即你摧毁了obj1的身体)时会发生什么?这似乎不正确。。。系统对你的父母关系一无所知,C++也没有内置参考计数系统。这可能也是问题所在。

如果你的目标是让一个游戏对象管理多个身体(即一群东西),那么让这个游戏对象维护一个多个身体的列表并管理它们。

然而,我相信你希望他们都像依恋一样移动。据我所知,只有两种方法可以让两个身体表现得像"一个"。

选项1:第一种是在它们之间使用关节。我在一个游戏中做到了这一点,当时我让一艘太空船撞上了一把武器。当船做到这一点时,我创建了一个棱柱形接头,这样枪就可以"安装"在船的前面。这是我用来附加它的代码:

void BulletLauncherEntity::CreateJointConnection()
{
   Entity* owner = GetOwner();
   Body& ownerBody = owner->GetBody();
   // We put the position of this at the tip of the
   // owner.
   float32 launcherDist = 0.5*(owner->GetScale())*Constants::SCALE_TO_METERS_RATIO();
   float32 launcherSize = 0.5*GetScale()*Constants::SCALE_TO_METERS_RATIO();
   // Joint along axis of entity
   b2PrismaticJointDef jointDef;
   // Note that the "Initialize" function in the
   // jointDef did not really give us what we wanted.
    jointDef.bodyA = &ownerBody;
    jointDef.bodyB = &GetBody();
    jointDef.localAnchorA = Vec2(launcherDist-launcherSize,0);
    jointDef.localAnchorB = Vec2::Zero();
    jointDef.localAxisA = Vec2(1,0);
    jointDef.referenceAngle = 0;
   jointDef.lowerTranslation = -launcherDist;
   jointDef.upperTranslation = 0.5*GetScale()*Constants::SCALE_TO_METERS_RATIO();
   jointDef.enableLimit = true;
   jointDef.maxMotorForce = 2.0;
   jointDef.motorSpeed = 0.25;
   jointDef.enableMotor = true;
   jointDef.collideConnected = false;
   ownerBody.GetWorld()->CreateJoint(&jointDef);
}

您也可以使用焊接接头。

但是根据手册,使用焊接接头不会产生"刚性"连接。它有一些柔软性,因为在碰撞过程中需要满足约束。

来自手册:

焊接接头试图约束两者之间的所有相对运动身体。请参阅试验台中的悬臂.h,了解焊接接头如何行为。使用焊接接头来定义可断裂性是很诱人的结构。但是,Box2D解算器是迭代的,因此关节是有点软。因此,通过焊接连接的身体链会弯曲。相反,最好从单个带有多个固定装置的车身。当身体破裂时,你可以摧毁夹具,并在新的机身上重新创建。请参见中的Breakable示例试验台。

我还没有试过测试这个,或者看看其他类型的关节有多"僵硬"。当我使用棱柱关节时,它对我来说似乎很坚固。但在碰撞过程中,它偶尔会被"推入"。

选项2:将其作为固定装置直接连接到车身上。我认为你将不得不创造摧毁旧的身体,并创造一套新的固定装置。

这有帮助吗?