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

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

Фигура Рэгдолла

У каждого 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 Проект / Видео


person Robert    schedule 28.08.2014    source источник
comment
Вам нужно использовать более длинные физические тела вместо кругов. Каждое физическое тело должно представлять собой руку, ногу, ступню, туловище и т. д. Ваше собственное тело состоит из костной структуры, которую вы здесь создали?   -  person ZeMoon    schedule 28.08.2014
comment
Я понимаю, что это неточное изображение человеческого тела, в данном случае это не так! На данный момент меня больше всего беспокоит странное поведение суставов.   -  person Robert    schedule 29.08.2014
comment
Вы пытались отключить гравитацию для отдельных тел?   -  person LearnCocos2D    schedule 29.08.2014
comment
Хотя я планирую в конечном итоге использовать гравитацию, гравитация в целом отключена на данный момент, пока я разбираюсь с проблемой суставов. Даже при включенной гравитации проблема все равно проявляется.   -  person Robert    schedule 29.08.2014
comment
Как вы переворачиваете персонажа вверх ногами?   -  person 0x141E    schedule 01.09.2014
comment
Я прикладываю силы к головному узлу, который эффективно тянет остальную часть тела. Если голова движется в сторону, а затем вниз, тело становится перевернутым.   -  person Robert    schedule 01.09.2014
comment
Я добавил некоторые дополнительные выводы к моему вопросу.   -  person Robert    schedule 01.09.2014
comment
У меня точно такая же проблема. Жаль, что это не исправлено в iOS 8 GM. Возможно, в 8.0.1… Удалось ли вам вручную ограничить ротацию? Я думаю попробовать применить противодействующий крутящий момент к телам в цикле обновления, когда они приближаются/ударяют/превышают мои желаемые пределы.   -  person Andy Barnard    schedule 12.09.2014
comment
Со своей стороны, у меня точно такая же проблема с движущейся цепью (мои звенья цепи проходят друг через друга). Удалось ли вам решить эту проблему и как, пожалуйста?   -  person Paul Giragossian    schedule 28.10.2014
comment
Боюсь, что нет, я рассматривал возможность ограничения суставов вручную, как предложил Энди, но решил, что это, вероятно, не сработает, и у меня недостаточно знаний о физических движках, чтобы заставить это работать. Я отправил сообщение об ошибке в Apple, и мой проект, по сути, приостановлен до тех пор, пока они ее не исправят!   -  person Robert    schedule 28.10.2014
comment
Эта же ошибка заставляет меня пересмотреть мой проект. Нет хорошего обходного пути для этого.   -  person BGreenstone    schedule 22.01.2015
comment
Я, возможно, столкнулся с той же проблемой. Основываясь на моих тестах, проблемы возникают, когда физический движок вращает тело в цепочке так, что его вращение сцены пересекает барьер PI. Посмотрите журнал, приведенный в конце здесь: stackoverflow.com/questions/28640019/   -  person Ian    schedule 15.03.2015
comment
Если это связано с поведением, с которым я столкнулся (^), возможно, Apple не планирует решать эту проблему.   -  person Ian    schedule 15.12.2015


Ответы (2)


"В настоящее время я использую значения -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
person Charlie Martin    schedule 05.03.2015
comment
Спасибо за ваш ответ, но я пробовал много разных углов; малый угол не является причиной. Я почти уверен, что проблема вызвана нормализацией SpriteKit углов поворота тела, когда они выходят за пределы своего предела и сбивают с толку лежащие в основе соединения Box2D. В любом случае, я не думаю, что ~ 5º слишком малы для расчетов физического движка, и он прекрасно справляется с ними, пока персонаж не перевернется вверх ногами! - person Robert; 05.03.2015
comment
Ну, все, что я могу вам сказать, это то, что я реализовал тряпичную куклу в SpriteKit, и у меня нет никаких проблем, когда она переворачивается вверх ногами. То, что вы пытаетесь сделать, возможно на 100%. - person Charlie Martin; 05.03.2015
comment
Когда я отправил отчет об ошибке, Apple попросила образец приложения/видео — я просто исправил его для современного Swift и повторно загрузил (все равно не получается), не стесняйтесь взглянуть (добавлена ​​ссылка на исходный пост); Мне было бы интересно узнать, что у вас есть! - person Robert; 05.03.2015
comment
Я посмотрю, смогу ли я заставить его работать, когда у меня будет немного свободного времени. Если нет, я заинтересован в отслеживании ошибки, так что спасибо. - person Charlie Martin; 05.03.2015
comment
Я не смог заставить его работать с размерами тела и углами, которые вы установили. Я заметил, что чем больше тела и углы, тем реже и реже это происходило, пока не исчезло совсем. Я также заметил, что это, по-видимому, происходит только в цепочках тел, что приводит меня к моей новой теории о том, что в процессе применения предела к первому суставу на теле он вытягивает другой сустав на том же теле за пределы досягаемости. . Похоже на ошибку. Интересным экспериментом было бы выяснить, возникает ли эта проблема в box2d без SpriteKit. Если да, то это может быть ограничение двигателя. Если нет, то это ошибка Spritekit. - person Charlie Martin; 07.03.2015
comment
Интересно, спасибо — я уверен, что видел подобные цепочки и прочее, работающее раньше в Box2D. Возможно, мне придется реализовать что-то подобное, чтобы узнать! - person Robert; 07.03.2015

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

person JakubKnejzlik    schedule 15.11.2015
comment
Также по этой причине мне пришлось использовать бурундука в моем проекте. - person JakubKnejzlik; 15.11.2015