Not Working Transitions in Spritekit

SKView.presentScene with transition not working if have shown another SKView

So, as spelled out in the course of my meandering question.

How to diagnose

Adding a deinit to do logging let me zero in on the difference between the two screens - one gets cleaned up and the other doesn't.

The Cause

in viewDidLoad the problem screen had this


// this line, in a method called from viewWillAppear. This is calling a simple drawing kit created by PaintCode
self.thicknessSwatch.drawer = { self.hasThickness ? LinePickerKit.drawEdgeThickness() : LinePickerKit.drawNoEdge() }

The fix, which is horribly obvious in retrospect:

self.thicknessSwatch.drawer = {[weak self] in (self?.hasThickness ?? false) ? LinePickerKit.drawEdgeThickness() : LinePickerKit.drawNoEdge() }

ie: my closure had a retain cycle on the UIViewController. That retained the SKView, even though it was not used, not bound to an outlet, only loaded from the xib.

The confusing behaviour was that the presence of that floating, semi-live SKView had no effect on most SpriteKit behaviour, until there was a presentScene(transition)

SKScene Present Scene Transition not Working with SpriteKit Scene in Swift

Why are you fading for 10 seconds? Seems long. Also is this the code in your GameViewController?

SKTransitions will only work when transitioning from 1 SKScene to another SKScene. Loading the first scene from your GameViewController will not use a transition since there is technically nothing to transition from.

As a side note, in swift 2 you can get rid of the extension to unarchive the SKScene. You can also just say (if you are using GameScene.sks)

if let scene = GameScene(fileNamed: "GameScene") {
...
}

Scene transition in spritekit not transitioning

The question mark comes from optional chaining because your scene property must have been declared like this SKScene?. This isn't a problem though, it just means that if your scene is nil, it won't get the size property.

The real problem is probably this line:

self.scene.view.presentScene(scene, transition: transition)

Reason being, your scene probably doesn't have a view before it's presented.

You probably wanted something like this:

(self.view as SKView).presentScene(scene, transition: transition)

You'll notice I said probably a lot. I'm only speculating on the problem because I don't see enough code, but I appreciate the effort to try and narrow down your problem. You should post more though because it may be somewhere else.

Edit

Try replacing this:

    let transitionToPlayScene = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)
if CGRectContainsPoint(playButton.frame, location) {
let playView = PlayScene(size: self.scene?.size)

}

With this

    if CGRectContainsPoint(playButton.frame, location) {
let transitionToPlayScene = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1.0)
let nextScene = PlayScene(size: self.size)
self.view!.presentScene(nextScene, transition: transitionToPlayScene)
}

SKView presentScene fails with transition

The solution I've stumbled across (in part thanks to this question) is to override my viewcontroller's loadView() and insert the following line

    self.view = UIView(frame: UIScreen.main.bounds)

This appears to cause everything else to fall into place. The transition now works as expected and intended, and there are not -as of yet- any unintended consequences!

SKTransition not working in Swift

SOLVED.

It turns out that there is nothing wrong with the code above. The problem was that I was trying to execute it in the update function based on a specific SKPhysicsBody's position. The transition doesn't happen instantaneously so it gave time for update to get called repeatedly which re-triggered the transition over and over again. This resulted in the transition never happening.

The fix was to add a bool to check if I have started the transition, so I only attempt it once.

SpriteKit scene transition good practices

Well the thing that was causing my trouble was inserting particle emitters every half second for 5 seconds using SKAction.repeatActionForever() to call the emitter insert function.

This repeatAction apparently was not killed by transitioning to another scene, and was causing the memory for the whole scene to be retained. I switched to SKAction.repeatAction() instead and specify how many time it should fire. The scene now returns all of its memory when I transition to the new scene.

I am not sure I understand this behavior though.



Related Topics



Leave a reply



Submit