Почему я получаю непрерывное столкновение между узлами SCNNode? - PullRequest
1 голос
/ 27 апреля 2020

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

В качестве первого шага я настроил свой класс на расширение SCNPhysicsContactDelegate:

class ViewController: SCNPhysicsContactDelegate
.
.
.
self.arSceneView.scene.physicsWorld.contactDelegate = self

I имеют 2 типа SCNNode: автомобиль и монеты . Для обоих я настроил категорию столкновений:

// Collisions
struct CollisionCategory: OptionSet {
    let rawValue: Int

    static let CoinsCategory = CollisionCategory(rawValue: 4)
    static let CarCategory = CollisionCategory(rawValue : 8)
}

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

Автомобиль

// Create physics shape
let boxBodyShape = SCNPhysicsShape(node: carNode, options: nil)

// Create physics body
let boxBody = SCNPhysicsBody(type: .kinematic, shape: boxBodyShape)

// Assign physics body
carNode.physicsBody = boxBody

// Setup category collisions properties
carNode.physicsBody?.categoryBitMask = CollisionCategory.CarCategory.rawValue
carNode.physicsBody?.contactTestBitMask = CollisionCategory.CoinsCategory.rawValue
carNode.physicsBody?.collisionBitMask = CollisionCategory.CoinsCategory.rawValue

Монета

// Create physics body
let boxBody = SCNPhysicsBody(type: .kinematic, shape: boxBodyShape)

// Assign physics body
coin.physicsBody = boxBody

// Setup category collisions properties
coin.physicsBody?.categoryBitMask = CollisionCategory.CoinsCategory.rawValue
coin.physicsBody?.contactTestBitMask = CollisionCategory.CarCategory.rawValue
coin.physicsBody?.collisionBitMask = CollisionCategory.CarCategory.rawValue

Последний шаг Я реализовал функцию physicsWorld(:didBegan:) для управления Столкновения:

func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
    print("A: \(contact.nodeA.name) - B: \(contact.nodeB.name)")
    print("A: \(contact.nodeA.physicsBody!.categoryBitMask) - B: \(contact.nodeB.physicsBody!.categoryBitMask)")
}

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

...
...
...
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin9")
...
...
...

Следующее изображение дает представление о ситуации на сцене:

image

Я не понимаю, что не так или чего не хватает в настройке.

Кажется, что когда машина находится рядом с какими-то кубиками (монетами), они влияют на нее, и поэтому происходит "столкновение", но я не не понимаю ...

image

Спасибо!

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Хорошо, я решил добавить этот элемент управления:

func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
    if(contact.penetrationDistance >= 0.08 && contact.nodeB.name!.contains("Coin")) {
        contact.nodeB.removeFromParentNode()
    }
}
0 голосов
/ 27 апреля 2020

Вы можете попробовать что-то вроде этого:

func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)
    {
        if(data.gameState == .run)
        {
            guard let nodeNameA = contact.nodeA.name else { return }
            guard let nodeNameB = contact.nodeB.name else { return }

            if(nodeNameA.prefix(5) == "Explo" && nodeNameB.prefix(5) == "Missi")
            {
                gameControl.enemyMissileHit(vIndex: Int(nodeNameB.suffix(4))!)
            }
            if(nodeNameA.prefix(5) == "Missi" && nodeNameB.prefix(5) == "Explo")
            {
                gameControl.enemyMissileHit(vIndex: Int(nodeNameA.suffix(4))!)
            }
            if(nodeNameA.prefix(5) == "Explo" && nodeNameB.prefix(5) == "Hive ")
            {
                gameControl.enemyHiveHit(vIndex: Int(nodeNameB.suffix(4))!)
            }
            if(nodeNameA.prefix(5) == "Hive " && nodeNameB.prefix(5) == "Explo")
            {
                gameControl.enemyHiveHit(vIndex: Int(nodeNameA.suffix(4))!)
            }
        }
    }
...