我的物理接触在 SpriteKit 中没有接触

My Physics Contacts are not making contact in SpriteKit

我正在使用 Xcode 7.3.1、iOS 9.3 和 Swift 2。还在模拟器和我的 iPad 上直接进行了测试。我进行了无数次搜索,阅读了 2 本 Spritekit Physics 书籍,观看了许多视频教程和书面教程。我以前写过 body 物理没有问题,也写过很多次小项目,但这个只是给我任何反馈。这个问题之前已经在特定实例中提出过,即 2 次碰撞与相同的 spritenode 或者 collisionBitMask 和 contactTestBitMask 之间的区别是什么。我知道其中的差异,也知道您希望联系的每个 object 都需要一个 categoryBitMask。

首先,我分配了一个全局 Physicsbody 结构(尝试了直接二进制 bitMask 和对应的 Int32,但都没有成功),一个物理委托和每个 SKSpritenode 对应于它的配对 contact/s。我已经尝试了多种方法来实现 didBeginContact(关于它的结构方式),none 比其他方法有所不同。

前面我提到了反馈。除了我的主要玩家 bullets、newEnemy 和 enemyFire 之外,我已经消除了所有玩家。当我尝试将接触或碰撞的结果打印到控制台时,就好像它甚至没有被读取一样。我没有 activity。这些 spritenode 都在 1 class (GameScene) 之内,我已经为每个功能性 spritenode 尝试了单独的 classes 但没有成功。此外,对于单独的 classes,它似乎让事情变得更糟,即使在 classes 和 sub-classes 之间有适当的通信协议。使用单独的 classes 对我来说仍然是新的,尽管我知道这是首选方式。我将只显示我认为可能需要查看的代码以最小化,但如果还有其他需要查看的内容,请告诉我。我只是想让子弹击中飞机,然后我可以从那里转到我的其他 objects。

import AVFoundation
import SpriteKit
import GameKit

// Binary connections for collision and colliding
struct PhysicsCategory {
    static let GroundMask : UInt32 = 1    //0x1 << 0
    static let BulletMask : UInt32 = 2    //0x1 << 1
    static let PlayerMask : UInt32 = 4    //0x1 << 2
    static let EnemyMask  : UInt32 = 8    //0x1 << 3
    static let EnemyFire  : UInt32 = 16   //0x1 << 4
    static let All        : UInt32 = UInt32.max // all nodes
}

class GameScene: SKScene, SKPhysicsContactDelegate {

    // Starting scene, passed to didMoveToView
    func startScene() {
    
        // Sets the physics delegate and physics body
        view?.showsPhysics = true
        self.physicsWorld.gravity = CGVectorMake(0, 0)
        self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
        self.physicsWorld.contactDelegate = self // Physics delegate set
    }

    func setupPlayer() {
    
        player = SKScene(fileNamed: "Player")!.childNodeWithName("player")! as! SKSpriteNode

        // Body physics for player's planes
        player.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "MyFokker2.png"), size: player.size)
        player.physicsBody?.dynamic = false
        player.physicsBody?.usesPreciseCollisionDetection = true
        player.physicsBody?.categoryBitMask = PhysicsCategory.PlayerMask
        player.physicsBody?.contactTestBitMask = PhysicsCategory.EnemyFire
        player.physicsBody?.collisionBitMask = 0
    
        player.removeFromParent()
        self.addChild(player) // Add our player to the scene
    }

    // Create the ammo for our plane to fire
    func fireBullets() {
    
        bullet = SKSpriteNode(imageNamed: "fireBullet")
    
        // Body physics for plane's bulets
        bullet.physicsBody = SKPhysicsBody(rectangleOfSize: bullet.size)
        bullet.physicsBody?.dynamic = false
        bullet.physicsBody?.usesPreciseCollisionDetection = true
        bullet.physicsBody?.categoryBitMask = PhysicsCategory.BulletMask
        bullet.physicsBody?.contactTestBitMask = PhysicsCategory.EnemyMask
        bullet.physicsBody?.collisionBitMask = 0
    
        self.addChild(bullet) // Add bullet to the scene
    }

    func spawnEnemyPlanes() {
        let enemy1 = SKScene(fileNamed: "Enemy1")!.childNodeWithName("enemy1")! as! SKSpriteNode
        let enemy2 = SKScene(fileNamed: "Enemy2")!.childNodeWithName("enemy2")! as! SKSpriteNode
        let enemy3 = SKScene(fileNamed: "Enemy3")!.childNodeWithName("enemy3")! as! SKSpriteNode
        let enemy4 = SKScene(fileNamed: "Enemy4")!.childNodeWithName("enemy4")! as! SKSpriteNode
    
        enemyPlanes = [enemy1, enemy2, enemy3, enemy4]
    
        // Generate a random index
        let randomIndex = Int(arc4random_uniform(UInt32(enemyPlanes.count)))
    
        // Get a random enemy
        newEnemy = (enemyPlanes[randomIndex])

        // Added randomEnemy's physics
        newEnemy.physicsBody = SKPhysicsBody(rectangleOfSize: newEnemy.size)
        newEnemy.physicsBody?.dynamic = false
        newEnemy.physicsBody?.usesPreciseCollisionDetection = true
        newEnemy.physicsBody?.categoryBitMask = PhysicsCategory.EnemyMask
        newEnemy.physicsBody?.contactTestBitMask = PhysicsCategory.BulletMask
        newEnemy.physicsBody?.collisionBitMask = 0
        
        newEnemy.removeFromParent()
        self.addChild(newEnemy)
    }

    func spawnEnemyFire() {
    
        enemyFire = SKScene(fileNamed: "EnemyFire")!.childNodeWithName("bullet")! as! SKSpriteNode
    
        enemyFire.removeFromParent()
        self.addChild(enemyFire) // Generate enemy fire
    
        // Added enemy's fire physics
        enemyFire.physicsBody = SKPhysicsBody(rectangleOfSize: enemyFire.size)
        enemyFire.physicsBody?.dynamic = false
        enemyFire.physicsBody?.usesPreciseCollisionDetection = true
        enemyFire.physicsBody?.categoryBitMask = PhysicsCategory.EnemyFire
        enemyFire.physicsBody?.contactTestBitMask = PhysicsCategory.PlayerMask
        enemyFire.physicsBody?.collisionBitMask = 0
    }

    func didBeginContact(contact: SKPhysicsContact) {
    
        if !self.gamePaused && !self.gameOver {
        
            // beginContact constants
            firstBody = contact.bodyA
            secondBody = contact.bodyB
        
            if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {    
                firstBody = contact.bodyA
                secondBody = contact.bodyB
            } else {   
                firstBody = contact.bodyB
                secondBody = contact.bodyA
            }

            // Contact statements
            if ((firstBody.categoryBitMask & PhysicsCategory.BulletMask != 0) && (secondBody.categoryBitMask & PhysicsCategory.EnemyMask != 0)) {   
                print("Bullet hit Enemy")
            }
            else if ((firstBody.categoryBitMask & PhysicsCategory.PlayerMask != 0) && (secondBody.categoryBitMask & PhysicsCategory.EnemyFire != 0)) {
                print("EnemyFire hit our Player")
            }
        }
    }
}

我试图省略明显的代码,但留下了需要知道的代码...如果它很长,我深表歉意。 我也尝试过 checkPhysics 函数,但它们甚至无法识别我的 objects。 所有 SpriteNodes 都传递给 didMoveToView 函数。 任何人都可以看出哪里出了问题或知道为什么我根本没有联系吗?

你遇到的问题是因为你所有的物理体都是非动态的。表示他们的动态 属性 设置为 falsedidBeginContact 只有至少有一个物体是动态的,才会调用方法。

来自docs

The dynamic property determines whether the body is simulated by the physics subsystem.

所以非动态物体肯定被排除在模拟之外。我找不到是否有某处记录这适用于接触,但根据我的经验,我非常肯定接触不会在两个静态物体之间工作。