Paris0
Paris0

Reputation: 1

unexpectedly found nil while unwrapping an Optional value in gamekit

i just simply trying to use SKEmitterNode and SKSpriteNode but i'm getting error on second line of my code

startfield.position = CGPoint.init(x:0,y:1200)

and error is like

"fatal error: unexpectedly found nil while unwrapping an Optional value"

Getting 2 times and also this one

"does not have sandbox access for frZQaeyWLUvLjeuEK43hmg and IS NOT appropriately entitled"

i didn't understand optional concept so because of that i'm not able to solve it ..

class GameScene: SKScene {

 var startfield : SKEmitterNode!
 var player : SKSpriteNode!

  override func didMove(to view: SKView) {
      startfield = SKEmitterNode(fileNamed: "Starfield")
      startfield.position = CGPoint.init(x: 0, y: 1200)
      startfield.advanceSimulationTime(10)
      self.addChild(startfield)
      startfield.zPosition = -1
        //define Player
    player = SKSpriteNode(imageNamed: "shuttle")
    player.position = CGPoint(x: self.frame.width/2, y: player.size.height/2 + 20)
    self.addChild(player)
  }

  override func update(_ currentTime: TimeInterval) {
      // Called before each frame is rendered
  }
}

Upvotes: 0

Views: 379

Answers (3)

Duncan C
Duncan C

Reputation: 131501

When you create a variable with a ! after the type, you make it "implicitly unwrapped". In practice, this means that if the variable is nil and you try to reference it, you crash.

Get rid of the ! in your declarations.

var startfield : SKEmitterNode?

And then change your didMove function to use a guard:

  override func didMove(to view: SKView) {
      startfield = SKEmitterNode(fileNamed: "Starfield")

      guard let startfield = startfield else {
         print("startfield is nil!")
         return
      }
      startfield.position = CGPoint.init(x: 0, y: 1200)
      startfield.advanceSimulationTime(10)
      self.addChild(startfield)
      startfield.zPosition = -1
        //define Player
    player = SKSpriteNode(imageNamed: "shuttle")
    player.position = CGPoint(x: self.frame.width/2, y: player.size.height/2 + 20)
    self.addChild(player)
  }

Upvotes: 0

user887210
user887210

Reputation:

The line:

startfield = SKEmitterNode(fileNamed: "Starfield")

Can return a nil if the file isn't found but you have it stored in an implicitly-unwrapped Optional:

var startfield : SKEmitterNode!

So the system treats it as non-nil but it's really nil. Then when you try to assign a property for that nil:

startfield.position = CGPoint.init(x: 0, y: 1200)
// should really be: CGPoint(x: 0, y: 1200)

Everything blows up and you get a fatal error.

Instead, check that the file loads correctly and then do your assignment:

override func didMove(to view: SKView) {
  // Load the file into a `SKEmitterNode?` and use optional binding 
  // to attempt to unwrap into a `SKEmitterNode`.
  guard let emitter = SKEmitterNode(fileNamed: "Starfield") else {
    // Unwrapping failed, crash with an appropriate message.
    fatalError("File \"Starfield\" not found.")
  }
  // Unwrapping succeeded, continue
  startfield = emitter
  // ...
}

The reason it loads into an SKEmitterNode? in the first place is due to the loading being performed in a failable initializer inherited from SKNode: init(fileNamed:)

convenience init?(fileNamed filename: String)

Optional Binding is when you use the construct if let to unwrap an Optional.

Upvotes: 1

Tom E
Tom E

Reputation: 1607

Redeclare your starfield variable (mistyped as startfield?) such that it allows nil values:

var starfield: SKEmitterNode?

This is necessary as SKEmitterNode(fileNamed:) is an optional initialiser, i. e. one that may return nil. Prior to further usage of this variable test if for not being nil, e. g. using a guard statement:

guard let starfield = starfield else { return }

For the remainder of your function starfield is non-nil now.

Upvotes: 1

Related Questions