SKPhysicsBody碰撞不起作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SKPhysicsBody碰撞不起作用相关的知识,希望对你有一定的参考价值。

下面是我的“Floor.swift”课程,下面基本上是一堆墙。我有来自屏幕顶部的对象,一旦Floor和SKSpriteNodes发生碰撞,我希望删除SKSpriteNode。以下是我的楼层课程。

import Foundation
import SpriteKit

class Floor: SKNode {
    override init() {
        super.init()

        let leftWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
        leftWall.position = CGPoint(x: 0, y: 50)
        leftWall.physicsBody = SKPhysicsBody(rectangleOf: leftWall.size)
        leftWall.physicsBody!.isDynamic = false
        self.addChild(leftWall)

        let rightWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
        rightWall.position = CGPoint(x: 375, y: 50)
        rightWall.physicsBody = SKPhysicsBody(rectangleOf: rightWall.size)
        rightWall.physicsBody!.isDynamic = false
        self.addChild(rightWall)

        let bottomWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 500, height: 10))
        bottomWall.position = CGPoint(x: 150, y: -5)
        bottomWall.physicsBody = SKPhysicsBody(rectangleOf: bottomWall.size)
        bottomWall.physicsBody!.isDynamic = false
        self.addChild(bottomWall)

        self.physicsBody = SKPhysicsBody(bodies: [leftWall.physicsBody!, rightWall.physicsBody!, bottomWall.physicsBody!])

        self.physicsBody?.categoryBitMask = floorCategory
        self.physicsBody?.contactTestBitMask = nailDropCategory | pointCategory | lifeCategory
        self.physicsBody?.collisionBitMask = balloonCategory
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemted")
    }
}

GameScene类下的“func didBegin(_ contact:SKPhysicsContact)”我写道:

func didBegin(_ contact: SKPhysicsContact) {        
        if (contact.bodyA.categoryBitMask == nailDropCategory | pointCategory | lifeCategory) && (contact.bodyB.categoryBitMask == floorCategory) {
           // contact.bodyB.node!.removeFromParent()
            print("COLLISION")
        }
}

如您所见,在我的Floor类中,我将对象设置为“self.physicsBody = SKPhysicsBody(bodies :)”和我的所有SKSpriteNode。但出于某种原因,我没有得到任何检测。我在我的objectCategory,pointCategory,lifeCategory的每个类上使我的“Floor”类成为“contactTestBitMask”。这是一个我一直坚持一分钟的问题,任何想法?

更新:

所以我现在正在使用下面的代码,它正在工作!唯一的问题是,默认情况是也删除我的“balloonCategory”,我不希望它这样做。我怎样才能让它只忽略那个类别,但也可以作为气球的一面墙?

func didBegin(_ contact: SKPhysicsContact) {
        let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

        switch contactMask {
        case balloonCategory | nailDropCategory:
            print("nailDrop and balloon have contacted.")
            contact.bodyB.node!.removeFromParent()
            self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
            lifeLost -= 1
        case balloonCategory | pointCategory:
            print("point and balloon have contacted.")
            contact.bodyB.node!.removeFromParent()
            totalPoints += 2
            self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
        case balloonCategory | lifeCategory:
            print("life and balloon have contacted.")
            contact.bodyB.node!.removeFromParent()
            lifeLost += 1
            self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
        default:            
            contact.bodyB.node!.removeFromParent()
            print("Removed (String(describing: contact.bodyB.node!.name))")
        }
    }
答案

听起来您可以从为所有对象类型分配名称中受益,例如:

class Balloon: SKSpriteNode {
    init() {
        super.init(texture: nil, color: .blue, size: CGSize(width: 50, height: 50))
        self.name = "balloon"
    }
}

现在,当您在交换机中进行检查时,可以在决定删除对象之前验证对象的身份。请参阅下面的switch语句中对默认大小写所做的更改。这样,如果节点是气球,则不会删除该节点。物理碰撞将继续发挥作用。

func didBegin(_ contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    switch contactMask {
    case balloonCategory | nailDropCategory:
        print("nailDrop and balloon have contacted.")
        contact.bodyB.node!.removeFromParent()
        self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
        lifeLost -= 1
    case balloonCategory | pointCategory:
        print("point and balloon have contacted.")
        contact.bodyB.node!.removeFromParent()
        totalPoints += 2
        self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
    case balloonCategory | lifeCategory:
        print("life and balloon have contacted.")
        contact.bodyB.node!.removeFromParent()
        lifeLost += 1
        self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
    default:
        if contact.bodyB.node!.name == "balloon" {
            print("Balloon collided but we will not remove it.")
            return
        } else {
            contact.bodyB.node!.removeFromParent()
            print("Removed (String(describing: contact.bodyB.node!.name))")
    }
}
另一答案

你不能保证nodeB是地板,而nodeA真的是nailDropCategory | pointCategory | lifeCategory吗?

我假设naildDroppointlife是3个对象,你想要在任何人触及floor时收到通知,所以尝试像这样构建你的didBegin(contact:)

  func didBegin(_ contact: SKPhysicsContact) {
     print("didBeginContact entered for (String(describing: contact.bodyA.node!.name)) and (String(describing: contact.bodyB.node!.name))")

     let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

     switch contactMask {
     case nailDropCategory | FloorCategory:
        print("nailDrop and floor have contacted.")
     case pointCategory | FloorCategory:
        print("point and floor have contacted.")
     case lifeCategory | FloorCategory:
        print("life and floor have contacted.")
     default:
        print("Undetected collision occurred")
     }
 }

你真的从Floor类创建了一个对象吗?

以上是关于SKPhysicsBody碰撞不起作用的主要内容,如果未能解决你的问题,请参考以下文章

来自纹理 swift SKphysicsbody 的碰撞问题

为啥 SKPhysicsBody -bodyWithEdgeLoopF​​romRect 不对碰撞做出反应?

当我不想时,SKShapeNode 与我的 SKPhysicsbody 发生碰撞

SpriteKit SKPhysicsBody 破碎碰撞

SpriteKit SKPhysicsBody 像一扇门一样的方向碰撞你只能穿过但不能回来

添加 SKPhysicsBody 会导致 SKSpriteNode 抖动