【问题标题】:SKPhysicsBody Collision Not WorkingSKPhysics身体碰撞不工作
【发布时间】:2023-03-26 03:27:01
【问题描述】:

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

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")
    }
}

“func didBegin(_contact:SKPhysicsContact)”下的GameScene类我写了:

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

如您所见,在我的 Floor 类中,我使用我的所有 SKSpriteNode 将对象设置为“self.physicsBody = SKPhysicsBody(bodies:)”。但由于某种原因,我没有得到任何检测。我让我的“Floor”类成为我的 objectCategory、pointCategory、lifeCategory 的每个类的“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))")
        }
    }

【问题讨论】:

  • nailDropCategory?点类别?生活类别?除了您之外,没有人知道您如何定义位掩码。
  • 好吧,我在所有其他类上定义了它,并且所有其他冲突都有效,所以我只是迷路了哈哈
  • 如果物理学已经在你的项目中起作用,那么这似乎应该起作用。您能否在示例项目中重现此问题并在 Github 上分享?似乎解决方案可能来自调试。
  • @peacetype 看看我的代码更新。我现在正在使用 switch 方法。在默认:部分中,它正在删除所有其他完美的节点,但我不希望它删除我的 balloonCategory,但我也不希望它在与我的 floorCategory 碰撞时删除它。我只是想让它成为它的一堵墙。我该怎么做?
  • @Dewan。您不能总是删除 nodeB 对象,因为您不知道哪个对象是 nodeA,哪个是 nodeB,但是有一种简单的方法可以解决这个问题。你能告诉我你想为每个联系人删除哪些节点吗?

标签: swift sprite-kit skphysicsbody


【解决方案1】:

听起来您将从为所有对象类型分配名称中受益,如下所示:

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))")
    }
}

【讨论】:

  • 伙计,我非常感谢您的帮助!你是一个祝福兄弟,我希望你有一个美好的新年!再次感谢你
  • 你也一样,祝你游戏好运!
  • 谢谢!最后一个问题,你个人最喜欢的 iOS 广告网络是什么?
  • 对不起,我无法回答这个问题,因为我从未使用过它们。我坚信设计适合有针对性的直接获利(付费应用、应用内购买或免费增值模式)。也就是说,如果您可以制作一款在休闲玩家中非常受欢迎的游戏,您可能会选择任何顶级广告网络并赚钱。只需谷歌 ios 的顶级广告网络,看看你会得到什么 :)
  • 你是个好人,祝你幸福。现在就去做,祝你好运!!
【解决方案2】:

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

我假设naildDroppointlife 是您希望在任何人触摸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 类中创建了一个对象?

【讨论】:

  • 它说,“didBeginContact 为 nil 和 nil 输入”并在开关中返回“默认值:”。此外,执行“self.physicsBody = SKPhysicsBody(bodies: [leftWall.physicsBody!, rightWall.physicsBody!, bottomWall.physicsBody!]) 行与我现有的physicsBody 重叠并导致一些问题。不太清楚发生了什么,因为这之前有效,所以我完全迷路了
  • 所以我们知道有什么东西发生了联系——确保场景中的每个节点都有一个名称,然后你就会知道发生了什么碰撞。当您说 self,physicsBody... 与现有物理体重叠时,我不确定您的意思是什么,因为根据您的代码,Floor 对象没有现有的物理体。
  • SKPhysicsBody 数组,其中包含所有主体以及这行代码“bottomWall.physicsBody = SKPhysicsBody(rectangleOf: bottomWall.size)”,我也为 leftWall 和 rightWall 做了。我实际上是在创建双物理体,它们是重叠的,所以在这一点上我不确定发生了什么。这压力很大
  • 看看我的代码更新。如果您帮我解决了问题,那么我会将您的问题标记为我的问题的答案,因为您帮我解决了这个问题
  • @Dewan 看起来你已经得到了答案,但是没有忽略联系人的代码(例如你的气球和墙),只是让这些联系人永远不会发生。即,如果您不想在气球接触墙壁时做任何事情,请不要设置他们的contactTestBitMasks,以便在他们接触时不会调用didBegin
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
相关资源
最近更新 更多