unwrapping SKPhysicsBody doesn't work

110 views Asked by At

In my project, I create new nodes using a class called RocketMaker. Inside this class, I have a function called applyRecurringForce()...

func applyRecurringForce() {
    var thrust: CGVector = CGVectorMake(100, 100)
    physicsBody!.applyForce(thrust)
}

My problem is I cannot access this function from the main scene.

override func update(currentTime: NSTimeInterval) {
    /* Called before each frame is rendered */
    for rocketNode in rocketShips.children {
        println("physicsBody: \(rocketNode.physicsBody.description)")
        rocketNode.physicsBody.applyRecurringForce()
    }
}

Starting with the above code, I get two errors, one for the println, and one for the call to applyRecurringForce().

Approach 1: No forced unwrapping...
1) The println error is "Value of optional type 'SKPhysiceBody' not unwrapped; did you mean to use '!' or '?'?" and proposes I force unwrap
2) The call returns "Cannot invoke 'applyRecurringForce' with no arguments"

Approach2: I add "!" following the suggested solution...
1) The println error is the same as for the previous approach": "Value of optional type 'SKPhysiceBody' not unwrapped; did you mean to use '!' or '?'?" and again it proposes I force unwrap
2) The call returns the same error as previously: "Cannot invoke 'applyRecurringForce' with no arguments"

Approach3: So I follow the chain, using "physicsBody!!" in both lines in the override function. This time, one of the two errors is removed...
1) The println error is gone
2) The call returns "'SKPhysicsBody does not have a member named 'applyRecurringForce'"

If I comment out the call, I get

physicsNodeName: type: representedObject:[ name:'rocket1' position:{56, 294} accumulatedFrame:{{16.849998474121094, 280.20001220703125}, {78.300003051757812, 27.5999755859375}}]

Does anyone have an idea what's up?? This double-unwrapping looks very strange to me.

1

There are 1 answers

2
Epic Byte On BEST ANSWER

Well your applyRecurringForce method is declared in your custom node class (RocketMaker), not the SKPhysicsBody class. So you need to change the inside of your for-loop to this:

println("physicsBody: \(rocketNode.physicsBody!.description)")
rocketNode.applyRecurringForce()

Also i'm not really sure what rocketShips is. I originally though it was an array but given that you are accessing the children property i'm going to assume it is some kind of SKNode. Usually you don't want to name a single node plural.

Assuming that rocketShips is a node, then you will need to cast its children to your custom node class because by default children is an array of AnyObject (which is why you see the double unwrapping). See below for full solution. Do note though that i'm casting the entire children array. If your array contains a mix of RocketMaster nodes and other nodes you will need to cast each child separately.

import SpriteKit
class GameScene: SKScene {
    var rocketShips: SKNode! //var rocketShips: [RocketMaster] = []
    override func update(currentTime: NSTimeInterval) {
        /* Called before each frame is rendered */
        for rocketNode in rocketShips.children as! [RocketMaster] {
            println("physicsBody: \(rocketNode.physicsBody!.description)")
            rocketNode.applyRecurringForce()
        }
    }
}

class RocketMaster: SKNode {
    func applyRecurringForce() {
        var thrust: CGVector = CGVectorMake(100, 100)
        physicsBody!.applyForce(thrust)
    }
}