swift - Buenas prácticas de transición de escena de SpriteKit
sprite-kit out-of-memory (1)
Bueno, lo que estaba causando mi problema era insertar emisores de partículas cada medio segundo durante 5 segundos usando SKAction.repeatActionForever () para llamar a la función de inserción del emisor.
Esta repeatAction aparentemente no se eliminó mediante la transición a otra escena, y estaba causando que la memoria de toda la escena se conservara. Cambié a SKAction.repeatAction () en su lugar y especifico la cantidad de tiempo que debería disparar. La escena ahora devuelve toda su memoria cuando paso a la nueva escena.
Sin embargo, no estoy seguro de entender este comportamiento.
Estoy escribiendo un juego usando SpriteKit con Swift y me he encontrado con un problema de memoria.
El diseño de mi juego es tal que GameViewController (UIViewController) presenta el primer SKScene (levelChooserScene) en la pantalla viewDidLoad. Esta escena no hace más que mostrar un montón de botones. Cuando el usuario selecciona un botón, la escena pasa a la escena correcta utilizando skView.presentScene, y cuando se completa el nivel, esa escena vuelve a la etapa levelChooserScene y el juego está listo para que el usuario seleccione el siguiente nivel.
El problema es que cuando se produce la transición de nuevo al levelChooserScene, la memoria asignada para la escena de juego no se desasigna, así que después de seleccionar solo unos pocos niveles, empiezo a recibir errores de memoria.
¿Es correcto mi diseño en la transición de SKScene a SKScene, o debería volver al GameViewController cada vez y luego pasar al siguiente SKScene desde allí?
He encontrado algunas publicaciones aquí que dicen que debería llamar skView.presentScene (nil) entre escenas, pero estoy confundido sobre cómo o dónde implementar eso.
Simplemente quiero pasar de un SKScene a otro y hacer que la memoria utilizada desde la escena saliente sea devuelta al sistema.
Este es un ejemplo de cómo he implementado SKScene:
class Level3: SKScene
{
var explodingRockTimer = NSTimer()
var blowingUpTheRocks = SKAction()
override func didMoveToView(view: SKView)
{
NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "dismissTheScene:", userInfo: nil, repeats: false)
var wait = SKAction.waitForDuration(0.5)
var run = SKAction.runBlock{
// your code here ...
self.explodeSomeRocks()
}
let runIt = SKAction.sequence([wait,run])
self.runAction(SKAction.repeatActionForever(runIt), withKey: "blowingUpRocks")
var dismissalWait = SKAction.waitForDuration(5.0)
var dismissalRun = SKAction.runBlock{
self.removeActionForKey("blowingUpRocks")
self.dismissTheScene()
}
self.runAction(SKAction.sequence([dismissalWait,dismissalRun]))
}
func explodeSomeRocks()
{
println("Timer fired")
}
//MARK: - Dismiss back to the level selector
func dismissTheScene()
{
let skView = self.view as SKView?
var nextScene = SKScene()
nextScene = LevelChooserScene()
nextScene.size = skView!.bounds.size
nextScene.scaleMode = .AspectFill
var sceneTransition = SKTransition.fadeWithColor(UIColor.blackColor(), duration: 1.5) //WithDuration(2.0)
//var sceneTransition = SKTransition.pushWithDirection(SKTransitionDirection.Down, duration: 0.75) //WithDuration(2.0)
//var sceneTransition = SKTransition.crossFadeWithDuration(1.0)
//var sceneTransition = SKTransition.doorwayWithDuration(1.0)
sceneTransition.pausesOutgoingScene = true
skView!.presentScene(nextScene, transition: sceneTransition)
}
}