SpriteKit - 使某些 SpriteNode 在不禁用其物理主体的情况下不会发生碰撞

hb2*_*b22 3 ios sprite-kit swift

我在屏幕上有 4 个 SpriteNode,我希望它们不要相互反弹,而是相互流动,同时保持与某些 SpriteNode 和屏幕框架的碰撞。我已经为所有这些声明了类别:

let BCategory  : UInt32 = 0x1 << 0
let B2Category : UInt32 = 0x1 << 1
let B3Category : UInt32 = 0x1 << 2
let B4Category : UInt32 = 0x1 << 3
let BotCategory : UInt32 = 0x1 << 4
let PadCategory : UInt32 = 0x1 << 5
let WallCategory : UInt32 = 0x1 << 6
Run Code Online (Sandbox Code Playgroud)

并添加了位掩码:

    b.physicsBody!.categoryBitMask = BCategory
    b2.physicsBody!.categoryBitMask = B2Category
    b3.physicsBody!.categoryBitMask = B3Category
    b4.physicsBody!.categoryBitMask = B4Category

    p.physicsBody!.categoryBitMask = PadCategory
    wall.categoryBitMask = WallCategory
    bot.physicsBody?.categoryBitMask = BotCategory

    b.physicsBody?.contactTestBitMask = BotCategory | PadCategory
    b2.physicsBody?.contactTestBitMask = BotCategory | PadCategory
    b3.physicsBody?.contactTestBitMask = BotCategory | PadCategory
    b4.physicsBody?.contactTestBitMask = BotCategory | PadCategory
Run Code Online (Sandbox Code Playgroud)

除了检查 SpriteNode 之间的碰撞外,我还想通过以下方式进行碰撞:

func didBeginContact(contact: SKPhysicsContact) {
Run Code Online (Sandbox Code Playgroud)

是否有可能让所有 b(b、b2、b3、b4)与 p、wall 和 bot 发生碰撞,但它们之间不发生碰撞?很感谢任何形式的帮助!

编辑:我遇到的问题是由 b(b、b2、b3、b4)表示的 SpriteNode 相互弹跳。我希望每个 b 只从 BotCategory 和 PadCategory 中包含的 SpriteNode 反弹,并滑过/穿过其他 b。

Ste*_*ves 5

你已经混淆了碰撞接触。碰撞是指两个物理体相互碰撞并弹开。碰撞完全由游戏引擎处理。您只需设置必要的collisionBitMask

接触是指 sprite-kit 游戏引擎告诉您 2 个物理体已接触的代码。然后,您可以制造一个爆炸,更新分数等。两个物体可以在没有通知您接触的情况下发生碰撞,或者它们可以在没有碰撞的情况下进行接触。您必须设置 contactTestBitMask,将您的程序设置为physicsWorld.contactDelegate并实现其中一个或两个didBeginContact/didEndContact功能。

两个物体是否碰撞由 控制collisionBitMask。默认情况下,这被设置为UInt32.Max即一切都与一切碰撞。给定两个物体,A 和 B,物体 A 可能会与物体 B 碰撞,即从物体 B 上弹开,但物体 B不会与物体 A 碰撞,即不受碰撞影响。

无论您的代码是否收到有关 2 个机构进行接触的通知,均由contactTestBitMask. 默认情况下设置为 0,即没有注册联系人。给定 2 个主体 A 和 B,您只需将主体 A 的 contactTestBit 掩码设置为主体 B 的类别,即可注册 2 个主体之间的所有接触。

我发现这个函数对于检查场景中的碰撞和接触很有用:

   func checkPhysics() {

        // Create an array of all the nodes with physicsBodies
        var physicsNodes = [SKNode]()

        //Get all physics bodies
        enumerateChildNodesWithName("//.") { node, _ in
            if let _ = node.physicsBody {
                physicsNodes.append(node)
            } else {
                print("\(node.name) does not have a physics body so cannot collide or be involved in contacts.")
            }
        }

        //For each node, check it's category against every other node's collion and contctTest bit mask
        for node in physicsNodes {
            let category = node.physicsBody!.categoryBitMask
            // Identify the node by its category if the name is blank
            let name = node.name != nil ? node.name : "Category \(category)"

            if category == UInt32.max {print("Category for \(name) does not appear to be set correctly as \(category)")}

            let collisionMask = node.physicsBody!.collisionBitMask
            let contactMask = node.physicsBody!.contactTestBitMask

            // If all bits of the collisonmask set, just say it collides with everything.
            if collisionMask == UInt32.max {
                print("\(name) collides with everything")
            }

            for otherNode in physicsNodes {
                if (node != otherNode) && (node.physicsBody?.dynamic == true) {
                    let otherCategory = otherNode.physicsBody!.categoryBitMask
                    // Identify the node by its category if the name is blank
                    let otherName = otherNode.name != nil ? otherNode.name : "Category \(otherCategory)"

                    // If the collisonmask and category match, they will collide
                    if ((collisionMask & otherCategory) != 0) && (collisionMask != UInt32.max) {
                        print("\(name) collides with \(otherName)")
                    }
                    // If the contactMAsk and category match, they will contact
                    if (contactMask & otherCategory) != 0 {print("\(name) notifies when contacting \(otherName)")}
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

只需在设置物理后调用它checkPhysics(),它就会列出哪些物体发生碰撞以及您将收到哪些联系人的通知。