Есть ли способ предотвратить сотрясение узла при сбоях во время столкновений?

#scenekit #physics #collision

#сценекит #физика #столкновение

Вопрос:

Функция (код ниже) просто перемещает символьный узел (contact.NodeA) обратно после того, как он проник в узел столкновения (contact.NodeB), через который ему запрещено проходить.

В сценарии, когда пользователь пытается переместить узел персонажа (contact.NodeA), пока он застрял в углу и т. Д. сцена/персонаж постоянно трясется/дает сбои, в то время как его положение постоянно удаляется от контакта.NodeB при 60 Гц.

Возможно ли с помощью SCNPhysicsContact в SceneKit в первую очередь предотвратить переход contact.NodeA в contact.NodeB? (т. е., почему вообще происходит «контакт. расстояние проникновения»? Почему мы не можем просто быть предупреждены, когда физический контакт начался без контакта.NodeA фактически переходит в контакт.NodeB? В конце концов, мы ловим контакт на «Дидбегине», но уже есть проникновение, которое мы должны скорректировать.)

(Когда пользователь пытается переместить узел персонажа, когда он «застрял» в углу или между двумя камнями и т. Д.)

Или есть другое решение для предотвращения повторного сотрясения contact.NodeA, поскольку его положение неоднократно корректируется, чтобы компенсировать его проникновение в контакт.NodeB? Трансформироваться вместо изменения положения?

Я уже пробовал установить momentum на 0.0 и удалить все анимации и т. Д. Однако, поскольку контакт все еще происходит с contact.NodeB, contact.NodeA не может быть удален, так как его импульс все еще останавливается во время контакта с NodeB.

Любая помощь будет очень признательна.

 private func characterNode(_ characterNode: SCNNode, hitWall wall: SCNNode, withContact contact: SCNPhysicsContact) {   if characterNode.name != "collider" { return }    if maxPenetrationDistance gt; contact.penetrationDistance { return }   var characterPosition = float3(characterNode.parent!.position)  var positionOffset = float3(contact.contactNormal) * Float(contact.penetrationDistance)    maxPenetrationDistance = contact.penetrationDistance  characterPosition.y  = positionOffset.y  replacementPositions[characterNode.parent!] = SCNVector3(characterPosition) }  extension GameViewController : SCNPhysicsContactDelegate {  func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {    if gameState != .playing { return }    contact.match(BitmaskWall) {  (matching, other) in    if other.name == "collider" {  self.characterNode(other, hitWall: matching, withContact: contact)  }  } }  

Комментарии:

1. похоже на код из демонстрационного приложения Apple Fox 🙂 Я заметил то же самое. К сожалению, я не могу сказать вам, что решает эту проблему — действительно хороший вопрос!

2. ЗАЙ: Действительно, вы правы. Я даже не осознавал этого. Я прошел курс «ты-болван», в котором, должно быть, в качестве учебного материала использовалась демонстрация Fox. Просматривая фактический код приложения Fox, я считаю, что следующая строка и все, что имеет отношение к ней, являются ответом. Я все еще пытаюсь это понять. Если я разберусь, я опубликую это в качестве ответа, чтобы помочь всем, кто может быть заинтересован. (В частности, «Модель collisionShapeOffsetFromModel»): Код персонажа!.simdWorldPosition = Точка замены — модель collisionShapeOffsetFromModel