SKPhysicsContact 主体,无法更改属性

SKPhysicsContact body, can't change properties

我在 didBegin(contact:) 中有一个 SpriteKit 物理接触触发。我为要移出屏幕的 Dot 对象的实例抓取物理体,但是当我尝试像这样更改其位置时,没有任何反应:

第一种方法

/* In GameScene.swift */

func didBegin(_ contact: SKPhysicsContact) {
    let dotBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask == 0b1 {
        dotBody = contact.bodyB
    } else {
        dotBody = contact.bodyA
    }

    if let dot = dotBody.node as? Dot {
        dot.position.x = 10000
    }
}

但是,如果我改为在我的 Dot class 中调用一个方法,传入那个正文,则位置设置正确:

第二种方法

/* In GameScene.swift */

func didBegin(_ contact: SKPhysicsContact) {
    let dotBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask == 0b1 {
        dotBody = contact.bodyB
    } else {
        dotBody = contact.bodyA
    }

    if let dot = dotBody.node as? Dot {
        dot.move()
    }        
}

这是圆点 class:

import SpriteKit
class Dot : SKSpriteNode {
    let dotTex = SKTexture(imageNamed: "dot")
    init() {
        super.init(texture: dotTex, color: .clear, size: dotTex.size())
        self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
        self.physicsBody?.categoryBitMask = 0b1 << 1
        self.physicsBody?.contactTestBitMask = 0b1
    }

    func move() {
        let reset = SKAction.run {
            self.position.x = 10000
        }
        self.run(reset)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

谁能解释为什么第二种方法中的位置变化有效但在我的第一种方法中不起作用?

这里是 link to the project on Github

编辑:

我认为这是因为您正在创建 SKSpriteNode 的子class,而不是创建 SKSpriteNode 的实例。除非您打算将其专门用于其他用途,否则我看不出这样做的理由。相反,我使用了这些

import Foundation
import SpriteKit

class Dot {

let dotSprite: SKSpriteNode

init() {
    dotSprite = SKSpriteNode(imageNamed: "Spaceship")
//        dotSprite.physicsBody = SKPhysicsBody(circleOfRadius: dotSprite.size.width/2)
//        dotSprite.physicsBody?.categoryBitMask = 0b1 << 1
//        dotSprite.physicsBody?.contactTestBitMask = 0b1

}

func move() {
    self.dotSprite.position.x = 0
}

func moveAnim(){
    let reset = SKAction.moveTo(x: 0, duration: 3)
    dotSprite.run(reset)
}

}

在我的 SKScene 中

import SpriteKit
import GameplayKit

class GameScene: SKScene {

let newDot = Dot()


override func didMove(to view: SKView) {

    self.addChild(newDot.dotSprite)
    newDot.dotSprite.setScale(0.5)
    newDot.dotSprite.position = CGPoint(x: frame.midX, y: frame.midY)

}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    newDot.dotSprite.position.x = 200
    newDot.moveAnim()

}

}

请注意,我已禁用物理体,因为我还没有创建另一个实体供它着陆(因此它会继续下落)。我还使用了宇宙飞船作为精灵。

所以现在您可以在点 class 中使用任何自定义方法。您也可以直接操作点 SpriteNode 的属性。同时创建多个实例。现在您可以在接触发生时直接更改它或调用点class中的方法进行移动。 希望这对您有所帮助。 :)

func didBegin(_ contact: SKPhysicsContact) {
  let hitDot = contact.bodyB.node! as! SKSpriteNode
  let hitDot1 = contact.bodyA.node! as! SKSpriteNode
    if hitDot.name? == "dot" || hitDot1.name? == "dot" {
       reset = true
    }        
}

   override func update(_ currentTime: TimeInterval) {
    if reset {
        newDot.position.x = 0
        reset = false
    }
}

我刚刚在这里编辑的代码中可能存在小错误。但希望这能给你这个想法。这应该可以正常工作。