无法将 PhysicsBody 和属性分配给 SKSpriteNode?

Posted

技术标签:

【中文标题】无法将 PhysicsBody 和属性分配给 SKSpriteNode?【英文标题】:Cannot assign PhysicsBody and property to an SKSpriteNode? 【发布时间】:2020-05-07 16:42:05 【问题描述】:

我正在构建一个函数,其中一个随机变量将在一个数组中选择 4 个 SKSpritenode 中的 1 个并将自己分配给它。然而,该随机线虽然按预期出现在屏幕上,但不包含任何物理体属性,因此它不会与其他节点发生碰撞。以下是我的代码:

func line() 

        redLine = SKSpriteNode(imageNamed: "redline")
        blueLine = SKSpriteNode(imageNamed: "blueline")
        yellowLine = SKSpriteNode(imageNamed: "yellowline")
        greenLine = SKSpriteNode(imageNamed: "greenline")

        let lineArray = [redLine,blueLine,yellowLine,greenLine]
        // Add physics
        lineArray[0].physicsBody?.categoryBitMask = gamePhysics.RedLine
        lineArray[1].physicsBody?.categoryBitMask = gamePhysics.BlueLine
        lineArray[2].physicsBody?.categoryBitMask = gamePhysics.YellowLine
        lineArray[3].physicsBody?.categoryBitMask = gamePhysics.GreenLine

        for i in 0...3 
            lineArray[i].physicsBody = SKPhysicsBody(circleOfRadius: 10)
            lineArray[i].physicsBody?.collisionBitMask = gamePhysics.RedBall | gamePhysics.BlueBall | gamePhysics.YellowBall | gamePhysics.GreenBall
            lineArray[i].physicsBody?.contactTestBitMask = gamePhysics.RedBall | gamePhysics.BlueBall | gamePhysics.YellowBall | gamePhysics.GreenBall
            lineArray[i].physicsBody?.affectedByGravity = false
            lineArray[i].physicsBody?.isDynamic = true
        
        let randomLine:SKSpriteNode! = lineArray.randomElement()
        ...

        self.addChild(randomLine)
        ...

        randomLine.run(SKAction.sequence([moveLine,delay,removeLine]))
    

所以基本上当随机线与其他节点碰撞时,什么都不会发生。

这是我的 didBegin(联系人)函数:

func didBegin(_ contact: SKPhysicsContact) 
        let firstBody = contact.bodyA
        let secondBody = contact.bodyB

        if firstBody.categoryBitMask == gamePhysics.RedBall && secondBody.categoryBitMask == gamePhysics.RedLine || firstBody.categoryBitMask == gamePhysics.BlueBall && secondBody.categoryBitMask == gamePhysics.BlueLine || firstBody.categoryBitMask == gamePhysics.YellowBall && secondBody.categoryBitMask == gamePhysics.YellowLine || firstBody.categoryBitMask == gamePhysics.GreenBall && secondBody.categoryBitMask == gamePhysics.GreenLine 

            currentScore += 1
            secondBody.node?.removeFromParent()
            print("hit point")

         else if firstBody.categoryBitMask == gamePhysics.RedLine && secondBody.categoryBitMask == gamePhysics.RedBall || firstBody.categoryBitMask == gamePhysics.BlueLine && secondBody.categoryBitMask == gamePhysics.BlueBall || firstBody.categoryBitMask == gamePhysics.YellowLine && secondBody.categoryBitMask == gamePhysics.YellowBall || firstBody.categoryBitMask == gamePhysics.GreenLine && secondBody.categoryBitMask == gamePhysics.GreenBall 

            currentScore += 1
            firstBody.node?.removeFromParent()
            print("hit point")

        
    

任何帮助将不胜感激! 编辑:这是球 func()。也许不知何故 SKNode 包含多个类别位掩码,因此不起作用?

func Ball() 

        ballNode = SKNode()
        redBall = SKSpriteNode(imageNamed: "redball")
        blueBall = SKSpriteNode(imageNamed: "blueball")
        yellowBall = SKSpriteNode(imageNamed: "yellowball")
        greenBall = SKSpriteNode(imageNamed: "greenball")

        let ballArray = [redBall,blueBall,yellowBall,greenBall]
        ...

        // Add physics
        ballArray[0].physicsBody?.categoryBitMask = gamePhysics.RedBall
        ballArray[1].physicsBody?.categoryBitMask = gamePhysics.BlueBall
        ballArray[2].physicsBody?.categoryBitMask = gamePhysics.YellowBall
        ballArray[3].physicsBody?.categoryBitMask = gamePhysics.GreenBall

        for i in 0...3 
            ballArray[i].physicsBody = SKPhysicsBody(circleOfRadius: 20)
            ballArray[i].physicsBody?.collisionBitMask = gamePhysics.RedLine | gamePhysics.BlueLine | gamePhysics.YellowLine | gamePhysics.GreenLine
            ballArray[i].physicsBody?.contactTestBitMask = gamePhysics.RedLine | gamePhysics.BlueLine | gamePhysics.YellowLine | gamePhysics.GreenLine
            ballArray[i].physicsBody?.affectedByGravity = false
            ballArray[i].physicsBody?.isDynamic = false
        

        ballNode.addChild(redBall)
        ballNode.addChild(greenBall)
        ballNode.addChild(yellowBall)
        ballNode.addChild(blueBall)

        self.addChild(ballNode)
    

更新 2: 这是我存储类别位掩码的结构:

struct gamePhysics 

    static let RedBall : UInt32 = 0x1 << 1
    static let BlueBall : UInt32 = 0x1 << 2
    static let GreenBall : UInt32 = 0x1 << 3
    static let YellowBall : UInt32 = 0x1 << 4
    static let RedLine : UInt32 = 0x1 << 5
    static let BlueLine : UInt32 = 0x1 << 6
    static let GreenLine : UInt32 = 0x1 << 7
    static let YellowLine : UInt32 = 0x1 << 8

【问题讨论】:

【参考方案1】:

您还记得在场景中设置联系人代理吗?将这行代码放入didMove(to:):

self.physicsWorld.contactDelegate = self

如果这不能解决问题,我会在&amp;&amp;|| 语句之间使用括号使didBegin 中的if 条件更加明确。

查看其余代码,我看不出还有什么问题,您所做的应该可以工作。您放置在 if 语句中的 print("hit point") 是否已到达?

【讨论】:

嗨,是的,我确实包含了 self.physicsWorld.contactDelegate = self 但它不起作用。而且 print("hit point") 根本没有运行,所以我认为有些东西阻止了代码进入那个 if 语句......最初我认为是因为我将“随机线”放在了 addChild 函数中。但是,当我尝试对单行使用 addChild 方法时,它仍然没有解决任何问题……也许该行已经以某种方式分配了物理体? categorybit 掩码不起作用? categoryBitMasks 的值是多少? 我将它存储在一个结构中,就像我对我的问题所做的编辑一样。这是一个 UInt32 值。【参考方案2】:

天哪,我找到了我的问题的答案。 categorybitmask 的值返回“nil”的原因是因为我实际上在指定其物理体之前将节点分配给 categorybitmask。将行向下移动几行,一切都解决了!

【讨论】:

以上是关于无法将 PhysicsBody 和属性分配给 SKSpriteNode?的主要内容,如果未能解决你的问题,请参考以下文章

无法将 PhysicsBody 添加到 SKSpriteNode(游戏崩溃)

Swiftui 无法分配给属性:'self' 是不可变的错误

无法分配给对象的只读属性“stopImmediatePropagation”

VueJS - 重新加载页面后无法将值从 mapState 分配给数据属性

尝试从 UIViewController 将属性分配给 UIScrollView 类

无法将符合协议的 Objective-C 类分配给具有 Swift 协议的属性