Я не видел никаких родительских отношений в Box2d, кроме отношения тело/крепление.
Мне кажется, что у вас есть obj1 и obj2, ссылающиеся на один и тот же объект, выделенный в памяти Box2d (тело). Когда вы удаляете объект obj1, например, вы, вероятно, удаляете прикрепленное к нему тело (выполняя что-то вроде world->DestroyBody(...)). При следующем обновлении box2d вы ссылаетесь на объект, который вы не выделили и приказали уничтожить (системе Box2d). Возможно в этом проблема?
Я также вижу, что вы делите прибор между obj2 и obj1. Что происходит, когда 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);
}
Также можно использовать сварной шов.
ОДНАКО, согласно руководству, использование сварных соединений не создаст "жесткого" соединения. У него есть некоторая мягкость, потому что ограничения должны выполняться во время столкновений.
ИЗ РУКОВОДСТВА:
Сварное соединение пытается ограничить все относительные движения между двумя телами. См. Cantilever.h на испытательном стенде, чтобы увидеть, как ведет себя сварной шов. Заманчиво использовать сварной шов для определения разрушаемых конструкций. Однако решатель Box2D является итеративным, поэтому соединения немного мягкие. Поэтому цепочки тел, соединенных сварными швами, будут изгибаться. Вместо этого лучше создавать разрушаемые тела, начиная с одного тела с несколькими креплениями. Когда тело ломается, вы можете уничтожить приспособление и воссоздать его на новом теле. См. пример Breakable на тестовом стенде.
Я не пытался проверить это или посмотреть, насколько «жесткими» являются другие типы суставов. Когда я использовал призматический шарнир, он показался мне довольно прочным. Но иногда его «вталкивают» во время столкновений.
Вариант 2. Прикрепите его как крепление непосредственно к корпусу. Я думаю, вам придется создать, уничтожить старый корпус и создать новый набор креплений только для этого.
Это помогло?
10.12.2013