节点过早地从场景中移除(Swift 游戏)

Node prematurely removed from scene (Swift game)

我在 Swift 中有以下代码用于一个简单的平台游戏:

import SpriteKit
import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var me : SKSpriteNode?
    var ceiling : SKSpriteNode?
    var studentTimer : Timer?
    var cloudTimer : Timer?
    let meCategory : UInt32 = 0x1 << 1
    let studentCategory : UInt32 = 0x1 << 2
    let cloudCategory : UInt32 = 0x1 << 3
    let groundAndCeilingCategory : UInt32 = 0x1 << 4

    var numberofStudents = 0
    var education = ["edu1", "edu2", "edu3", "edu4"]

    override func didMove(to view: SKView) {

        physicsWorld.contactDelegate = self

        me = childNode(withName: "me") as? SKSpriteNode
        me?.physicsBody?.categoryBitMask = meCategory
        me?.physicsBody?.contactTestBitMask = studentCategory
        me?.physicsBody?.collisionBitMask = groundAndCeilingCategory

        // make me run
        var meRun : [SKTexture] = []
        for number in 1...6 {
            meRun.append(SKTexture(imageNamed: "Armature_Run_\(number)"))
        }
        me?.run(SKAction.repeatForever(SKAction.animate(with: meRun, timePerFrame: 0.1)))

        ceiling = childNode(withName: "ceiling") as? SKSpriteNode
        ceiling?.physicsBody?.categoryBitMask = groundAndCeilingCategory
        ceiling?.physicsBody?.collisionBitMask = meCategory

        startTimers()
    }

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

        me?.physicsBody?.applyForce(CGVector(dx: 0, dy: 20000))

        var meJump : [SKTexture] = []
        for number in 0...9 {
            meJump.append(SKTexture(imageNamed: "Armature_Jump_0\(number)"))
        }
        me?.run(SKAction.animate(with: meJump, timePerFrame: 0.1))
    }

    func createStudent() {

        let student = SKSpriteNode(imageNamed: "student")
        student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
        student.physicsBody?.affectedByGravity = false
        student.physicsBody?.categoryBitMask = studentCategory
        student.physicsBody?.contactTestBitMask = meCategory
        student.physicsBody?.collisionBitMask = 0
        addChild(student)
        student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height)*2))
        let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
        student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
    }

    func startTimers() {

        studentTimer = Timer.scheduledTimer(withTimeInterval: 4, repeats: true, block: { (timer) in
            if self.numberofStudents < 4 {
            self.createStudent()
            }
        })

        cloudTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { (timer) in
            self.createCloud()
        })
    }

    func createCloud() {

        let cloud = SKSpriteNode(imageNamed: "cloud")
        cloud.zPosition = -1
        cloud.physicsBody = SKPhysicsBody(rectangleOf: cloud.size)
        cloud.physicsBody?.affectedByGravity = false
        cloud.physicsBody?.collisionBitMask = 0
        cloud.physicsBody?.categoryBitMask = cloudCategory
        addChild(cloud)
        let maxY = size.height / 2 - cloud.size.height / 2
        let minY = CGFloat(0)
        let range = maxY - minY
        let cloudY = maxY - CGFloat(arc4random_uniform(UInt32(range)))
        cloud.position = CGPoint(x: size.width / 2 + cloud.size.width / 2, y: cloudY)
        let moveLeft = SKAction.moveBy(x: -size.width - cloud.size.width, y: 0, duration: 4)
        cloud.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
    }

    func didBegin(_ contact: SKPhysicsContact) {

        if contact.bodyA.categoryBitMask == studentCategory {
            contact.bodyA.node?.removeFromParent()
            numberofStudents += 1
            print(numberofStudents)
            print(education[(numberofStudents)-1])
        }

        if contact.bodyB.categoryBitMask == studentCategory {
            contact.bodyB.node?.removeFromParent()
            numberofStudents += 1
            print(numberofStudents)
            print(education[(numberofStudents)-1])
        }
    }
}

我正在研究当主角 ("me") 与 "student" 相撞时会发生什么。

在添加 'physicsWorld.contactDelegate = self' 之前,"student" 完美显示,在屏幕上移动。但是,当我添加这行代码和 运行 应用程序时,学生是不可见的。我相信它仍然存在于某个地方,因为当角色发生碰撞时,打印公用语仍然是 运行ning,但它并没有明显地与任何东西发生碰撞。

我删除了 contact.bodyB.node?.removeFromParent() 和 运行 它,确实 "student" 确实再次显示,但显然不会在联系时消失。

我已经研究了很久,确信我遗漏了一些明显的东西,但无法弄清楚它是什么。

您没有向我们提供所有信息。

因为您的代码按预期工作。

这是您的代码的视频 运行(我必须使用自己的图片)

下面是我对可能错误的分析。

我删除了所有动画序列项目,因为它们与此无关。

我注意到你没有放置 zPositions...tsk tsk tsk。所有项目都应该有一个 zPosition。

您没有向我们展示如何在 "me" 精灵上定义 physicsBody。大概在编辑器里?下次你应该包括那个信息。

我必须创建 "me" 字符并将其放置在代码中,因为您没有向我们展示它的来源。我还在代码中创建了 physicsBody 以使其工作。

这是我使用的代码

me = SKSpriteNode(imageNamed: "orange")
me.position = CGPoint(x: -400, y: (-size.height / 2) + ((me.size.height) * 2))
me.zPosition = 10
addChild(me)

me.physicsBody = SKPhysicsBody(rectangleOf: me.size)
me.physicsBody?.categoryBitMask = meCategory
me.physicsBody?.contactTestBitMask = studentCategory
me.physicsBody?.collisionBitMask = groundAndCeilingCategory
me.physicsBody?.affectedByGravity = false

func createStudent() {

    let student = SKSpriteNode(imageNamed: "apple")
    student.setScale(0.5)
    student.position = CGPoint(x: size.width / 2 + student.size.width, y: (-size.height / 2) + ((student.size.height) * 2))
    student.zPosition = 10
    addChild(student)

    student.physicsBody = SKPhysicsBody(rectangleOf: student.size)
    student.physicsBody?.affectedByGravity = false
    student.physicsBody?.categoryBitMask = studentCategory
    student.physicsBody?.contactTestBitMask = meCategory
    student.physicsBody?.collisionBitMask = 0

    let moveLeft = SKAction.moveBy(x: -size.width - student.size.width, y: 0, duration: 4)
    student.run(SKAction.sequence([moveLeft, SKAction.removeFromParent()]))
}

附带说明一下,没有必要使用计时器。 SpriteKit 有一个内置功能 "update" func.