Неправильное поведение с SKPhysicsJointPin, когда shouldEnableLimits имеет значение true, а параметры lowerAngleLimit и upperAngleLimit установлены

В настоящее время у меня есть фигура тряпичной куклы, которая состоит из родительского узла (без прикрепленных физических тел) и множества дочерних узлов, каждый из которых состоит из тела круга. Круги связаны друг с другом с помощью SKPhysicsJointPin между каждым кругом, как так:

Ragdoll фигура

каждый SKPhysicsJointPin имеет shouldEnableLimits = trueи в настоящее время я использую значение -0,05 и 0,05 для lowerAngleLimit а также upperAngleLimit соответственно.

Это работает довольно хорошо и предотвращает слишком сильную деформацию фигуры, за исключением случаев, когда фигура переворачивается в целом, и в этом случае все суставы внезапно пытаются сжаться, вот так:

Сломанная тряпичная фигура

Суставы сжимаются очень быстро, когда фигура полностью перевернута. Когда он снова поворачивается, все суставы возвращаются в норму. Почему это происходит? Как мне поддерживать правильные углы на суставах?

Изменить 1:

Я просто попытался переписать проект в Objective-C на случай, если это произошло из-за какой-то странной ошибки Swift; Оказывается, эта проблема все еще проявляется в Objective-C, поэтому я удалил тег Swift.

Мое лучшее предположение на данный момент состоит в том, что угол соединения относительно мира неправильно рассчитывается SpriteKit, когда тела, к которым они прикреплены, повернуты более чем на 180° в любом направлении, и поэтому неправильные углы передаются на основные суставы Box2D.

Я не был уверен, должен ли я постоянно обновлять пределы нижнего и верхнего углов, чтобы они соответствовали мировым углам их тел, но мне не кажется, что когда тело очень близко к перевернутому, суставы перестают работать правильно. Я все равно буду продолжать экспериментировать...

Изменить 2:

Теперь я уверен, что проблема возникает из-за того, что SpriteKit (я думаю, на то есть веские причины) изменяет zRotation значение, чтобы держать его между -180° и 180°. Например, если узел вращается по часовой стрелке и достигает -180°, SpriteKit автоматически оборачивает свое значение обратно до +180°. Я вполне уверен, что это обтекание приводит к хаотичному поведению суставов, мне просто нужно выяснить, как этому противодействовать...

Изменить 3:

Я загрузил образец приложения (включая видео), который демонстрирует эту проблему, как первоначально просил Apple: Xcode Project / Video

2 ответа

Я могу подтвердить, что это ошибка в SpriteKit. В моем случае я использую самый простой сценарий двух спрайтов, соединенных штифтовым соединением. К сожалению, это все еще происходит на iOS 9:(

"В настоящее время я использую значения -0,05 и 0,05 для lowerAngleLimit и upperAngleLimit соответственно"

Согласно документам...

upperAngleLimit - Наибольший угол, допустимый для штифтового соединения, в радианах.

... пределы в радианах.

0.05 radians = 2.86478898 degrees

Таким образом, вы позволяете телам двигаться только на 5 градусов. Это очень маленький диапазон. По моему опыту, SpriteKit начинает это странное поведение, когда тело выталкивается из зоны действия.

Я не думаю, что это поведение характерно для перевернутых тел. Мое лучшее предположение состоит в том, что физический движок не имеет частоты кадров, чтобы применить силу тяжести в одном кадре и поймать тело, прежде чем оно выйдет за пределы диапазона в следующем.

Вы должны увеличить диапазон. Я предпочитаю указывать это в градусах. Например...

func degreesToRadians(degrees: CGFloat) -> CGFloat {
    return CGFloat(M_PI) * degrees / 180.0
}

pinJoint.shouldEnableLimits = true
pinJoint.lowerAngleLimit = degreesToRadians(-30.0)
pinJoint.upperAngleLimit = degreesToRadians(180.0)

Вам придется повозиться с углами, массой и гравитацией, пока вы не найдете сладкое место, где все реально движется.

Если вы действительно хотите небольшой диапазон движения, я бы подумал просто отключить его.

circle.physicsBody?.allowsRotation = false
Другие вопросы по тегам