so I am trying to add an SKSpritenode to my scene level2, and I want to give it a physics body with a texture that comes from an image I have uploaded into the assets folder of my project. the image is there and the name is right, but when launch the app I get a fatal error. I don't get where I'm going wrong as the app used to run smoothly until I added that last line of code.
import UIKit
import SpriteKit
import GameplayKit
class level2: SKScene {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
var perno = SKSpriteNode(fileNamed: "perno")
override func sceneDidLoad () {
print ("view2 Loaded")
self.perno = self.childNode(withName: "perno") as? SKSpriteNode
self.perno?.texture = SKTexture(imageNamed: "perno")
self.perno?.size.width = self.perno!.size.width * 5
self.perno!.physicsBody = SKPhysicsBody(texture: (perno?.texture)!, size: (perno?.texture?.size())!)
}
any hints?
Thanks!
Your optional handling is really inconsistent. Sometimes you use optional casting and optional chaining just to then use force unwrapping on the same variable in the same line. You should force unwrap the return value of SKSpriteNode(fileNamed: "perno")
, since if that returns nil
that's a programmer error and should be caught ASAP.
Your immediate issue seems to be that you try to overwrite perno
in sceneDidLoad
:
self.perno = self.childNode(withName: "perno") as? SKSpriteNode
There's no childNode
added to your scene, so you just set perno
to nil
instead of its previously set value using var perno = SKSpriteNode(fileNamed: "perno")
. Simply remove that line from sceneDidLoad
, since it makes no sense, perno
is already loaded during initialisation, since you assign a value to it.
class Level2: SKScene {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
let perno = SKSpriteNode(fileNamed: "perno")!
override func sceneDidLoad () {
print ("view2 Loaded")
self.perno.texture = SKTexture(imageNamed: "perno")
self.perno.size.width = self.perno.size.width * 5
self.perno.physicsBody = SKPhysicsBody(texture: perno.texture!, size: perno.texture!.size())
}
}
A better way to protect yourself is to use the guard
statement. guard
allows you to safely check if a variable is not nil without having to nest your code.
class Level2: SKScene {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
let perno = SKSpriteNode(fileNamed: "perno")!
override func sceneDidLoad () {
print ("view2 Loaded")
guard let texture = SKTexture(imageNamed: "perno")
else{
fatalError("Unable to find texture "perno")
}
self.perno.texture = texture
self.perno.size.width = self.perno.size.width * 5
self.perno.physicsBody = SKPhysicsBody(texture: texture, size: texture.size())
}
}
As you can see, we are not excessively unwrapping self.perno.texture
, which means there will be less chances for us to accidentally use a ? instead of a !, and we have a clear cut error as to why our code is crashing.