How to dismiss SKScene?
Asked Answered
F

7

16

When Im finished with my SKScene is there a way to dismiss the SKScene from within my SKScene class?

If not back in my Viewcontroller where I present my SKScene [skView presentScene:theScene]; is there a way to restart the scene or remove in from my SKView?

The SKScene Class Reference and SKView Class Reference are no help.

Update:

The following code removes my scene from my SKView [yourSKView presentScene:nil]; but when Im back in my view controller the scene is still running in the background. I can always pause it when the game is over and I'm sent back to my view controller(menu) but I'm wondering is there another method other then pausing it like completely removing it?

-(void)endTheGame {
    [highscoreLabel removeFromSuperview];
    NSLog(@"Game Over");
   //would like to end here before calling the below method in my view controller
    [self.delegate mySceneDidFinish:self];
}
Forestforestage answered 20/2, 2014 at 21:46 Comment(3)
dismiss the view controller? After all if you no longer want to present a scene you can (and should) just do away with the SKView altogether.Labyrinthine
Did you manage to solve it? I have the same issue.. Cannot go back to the view controller from the sceneGovern
You can't go "Back to the View Controller" from a scene. The scene is a View, the view controller controls and displays views. Use the view controller to change views. Remember the view controller itself is not a view.Shakti
F
4

"You can't go "Back to the View Controller" from a scene. The scene is a View, the view controller controls and displays views. Use the view controller to change views. Remember the view controller itself is not a view." -Wharbio

Best solution here is to create another View Controller. This view controller will be my menu. Then the other viewcontroller will act as a host for the skscene.

In my situation I then use my menu viewcontroller to dismiss the viewcontroller displaying in the skview.

Forestforestage answered 11/8, 2014 at 18:16 Comment(1)
Is there no other way. If I do it like that I get a lot of memory warnings and from time to time my game crashes?Fabio
S
14

Having met a similar issue I stumbled around your question, and since nobody gave a decent answer here's how I solved it:

  1. in my scene I called both lines
[self removeFromParent];
[self.view presentScene:nil];
  1. in my controller (the controller that displays the SKScene) I changed the template code from Apple, which was creating and presenting my scene from viewDidLoad in order to create and present my scene in viewWillAppear, only if the view's scene is nil

here's my Swift code, even if you're using Objective C you'll understand what it does; the key line being the "if skView.scene == nil" test :

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    let skView = self.view as SKView
    if skView.scene == nil {
        let scene = GameScene(size:skView.bounds.size)
        scene.controller = self
        skView.ignoresSiblingOrder = true
        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
    }
}
Swarm answered 12/12, 2014 at 5:53 Comment(1)
If your answer was less confusing it would help. You have a mix of swift and objective c. I'm not sure your code fragments agree with your text. You mention view controller but show a routine from the game scene? In my case, I set two breakpoints in the view controller, one in viewdidload and the other in viewwillappear. Both hit when starting, but neither hit after the method you used in the game scene in step 1.Oestradiol
T
11

You can use:

 [yourSKView presentScene:nil];

to remove the scene.

Toms answered 20/2, 2014 at 22:2 Comment(8)
awesome yes that removes the scene from my skview but when Im redirected to the menu the scene is still running in the background? Other then pausing the scene when the game is over is there another method?Forestforestage
Is the menu in the parent view controller? Can you post the code you use to go to the menu?Toms
Yes the menu is the parent view controllerForestforestage
How is it still running if you've set it to nil? Have you considered putting the menu in a separate view controller? So VC1 has the menu which can call VC2 which hosts the SKScene. When the game is over, have VC1 dismiss VC2Toms
yeay I have just seems like a lot of work thats needed for just stopping a scene don't you think? Im not sure why its still running I did set it to nil..Forestforestage
I prefer using two VCs, gives better control and guarantees your SKScene will be removed, along with its memory usage. You can still use VC2 to pause the game but if you want to remove it, use VC1. Also I usually put a menu in the SKScene itself with functions like pause to restart.Toms
alright I will leave the question open to other answers thoughForestforestage
When I do this in my view controller, the scene is released entirely, it is not still running. You shouldn't need two view controllers to stop the scene, it's more likely that there's a retain cycle somewhere holding the scene in memory. This used to be a bug in SpriteKit, where SKScenes were retained even after it, but that's fixed now. So if this is still a problem, the retain cycle would be in your code somewhere.Disapproval
F
4

"You can't go "Back to the View Controller" from a scene. The scene is a View, the view controller controls and displays views. Use the view controller to change views. Remember the view controller itself is not a view." -Wharbio

Best solution here is to create another View Controller. This view controller will be my menu. Then the other viewcontroller will act as a host for the skscene.

In my situation I then use my menu viewcontroller to dismiss the viewcontroller displaying in the skview.

Forestforestage answered 11/8, 2014 at 18:16 Comment(1)
Is there no other way. If I do it like that I get a lot of memory warnings and from time to time my game crashes?Fabio
T
2

From within your SKScene, you can simply do [self.view presentScene:aNewScene] to present another scene

Tokay answered 20/2, 2014 at 21:53 Comment(2)
that seems to be everyones solution from my search for this answer. but this is not what I want. I want to go back to the menu (which i successfully already do) in my view controller. The probably is when I'm back in my menu and you go to click the button to start the game again and present the scene its in the exact same place it left off. Hense the reason I need to somehow dismiss or restart the scene.Forestforestage
Are you sure you are presenting a new scene, i.e by performing alloc / init, and not an existant scene saved in an ivar ?Tokay
S
2

I completely remove scenes by using this block in my view controller: Obviously you will need to declare your Size, and "newSKview"

SKView * skView = (SKView *)self.view;

SKScene *newScene = [[newSKView alloc]initWithSize:size];
newScene.scaleMode = SKSceneScaleModeAspectFill;
SKScene *oldScene=(skView.scene);
[oldScene removeFromParent];
[skView presentScene:newScene];

This works fine for me. None of my Scenes are retained or strong.

Shakti answered 24/7, 2014 at 3:58 Comment(0)
R
-1

I prefer to use an additional UIViewController for SKView and Notification Center in where the UIViewController made SkScene.

The callback function is

@objc func cb_dismissingVC(_ notificaiton: Notification) {
    self.dismiss(animated: true, completion: nil)
}
Rory answered 27/9, 2021 at 4:35 Comment(0)
G
-4

Maybe my variant will be helpful:

[[self.scene childNodeWithName:@"YourChildNodeName"] removeFromParent];
Gertrudis answered 17/4, 2014 at 13:10 Comment(1)
The OP is asking how to remove scenes, not nodesKlagenfurt

© 2022 - 2024 — McMap. All rights reserved.