Ich muss die Spielszene freigeben, nachdem der Spieler ein Level beendet hat, so dass der Speicher verfügbar ist, um ein anderes Level meines Spiels zu laden. Wenn ich das nicht mache, stürzt meine App wegen Speicherproblemen ab.Swift, SpriteKit: Eine Gamescene freischalten und eine neue zuweisen
Ich habe die Hinweise dort gegeben gefolgt:
Swift: Deallocate GameScene after transition to new scene?
Aber leider ist es für mich nicht funktioniert. Ich erhalte eine Fehlermeldung „Could not Wert‚UIView‘gegossen‚SKView‘in meiner GameViewController Klasse Hier ist meine ganze Code:.
import Foundation
import UIKit
import SpriteKit
class GameViewController: UIViewController {
var scene1: SKScene?
var scene2: SKScene?
var scene3: SKScene?
var skView: SKView?
func nextSceneAction1() {
scene2 = nil
scene3 = nil
skView! = self.view as! SKView
skView!.showsFPS = true
skView!.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView!.ignoresSiblingOrder = true
scene1 = TransitionSigns(size: skView!.frame.size)
scene1!.size.width = 2048
scene1!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene1!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene1!.scaleMode = .AspectFill
skView!.presentScene(scene1!, transition: transition)
}
func nextSceneAction2() {
scene1 = nil
scene3 = nil
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene2 = TransitionSigns(size: skView.frame.size)
scene2!.size.width = 2048
scene2!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene2!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene2!.scaleMode = .AspectFill
skView.presentScene(scene2!, transition: transition)
}
func nextSceneAction3() {
scene1 = nil
scene2 = nil
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene3 = TransitionSigns(size: skView.frame.size)
scene3!.size.width = 2048
scene3!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene3!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene3!.scaleMode = .AspectFill
skView.presentScene(scene3!, transition: transition)
}
override func viewWillLayoutSubviews() {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
let scene = MainView(size: skView.frame.size)
scene.size.width = 2048
scene.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return UIInterfaceOrientationMask.AllButUpsideDown
} else {
return UIInterfaceOrientationMask.All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidDisappear(animated: Bool) {
self.view.removeFromSuperview()
}
override func viewWillDisappear(animated: Bool){
self.view.removeFromSuperview()
}
}
ich die verschiedenen Funktionen aufrufen nextSceneAction1()
, nextSceneAction2()
und nextSceneAction3()
von meinen anderen Klassen mit :
let controller1 = GameViewController()
controller1.nextSceneAction1()
oder
let controller2 = GameViewController()
controller2.nextSceneAction1()
Wenn die neue Szene geladen wird, bekomme ich diesen Fehler: „Kann nicht Wert vom Typ‚UIView‘gegossen "SKView". Weißt du, was mit diesem Code falsch ist?
Übrigens bin ich offen mit allen anderen Möglichkeiten, alte Szene aus dem Speicher zu löschen, bevor Sie eine neue laden, so dass es während der Lebensdauer der App keinen Speicherabsturz gibt.
Dank hilft, so scheint es, alle Texturen aus den spritesheets bleiben jedoch in Speicher, auch wenn die Szene vom Bildschirm verschwunden ist. Es ist mir gelungen, die Speicherauslastung zu reduzieren, indem ich alle meine 2040X2048-Texturen durch eine sehr kleine PNG-leere Textur von 160 Bytes von 10X10 Pixeln ersetze. Dies reduziert den Speicherverbrauch meines Spiels von mehreren hundert MB, wenn eine Szene verschwunden ist und durch eine neue ersetzt wurde ... – PGibouin
Dies ist normales Verhalten. SpriteKit speichert die Textur für die Performance. Ich würde sie nicht freigeben, lass SpriteKit es für dich tun. – crashoverride777
Um hinzuzufügen. Gehen Sie zu Ihren SKScenes und fügen Sie die Methode demin (siehe aktualisierte Antwort) mit einer print-Anweisung hinzu.Wenn deinit angerufen wird, weißt du, dass die ganze Szene korrekt freigegeben wurde, wenn du kein Speicherleck hast. Auf diese Weise ist es einfacher zu sehen, was passiert, weil SpriteKit viele Dinge im Hintergrund erledigt, z. B. das Textur-Caching. – crashoverride777