2016-05-06 2 views
0

Je travaille actuellement sur un jeu pour iOS utilisant SpriteKit et j'ai rencontré un crash bizarre lors de la mise en place de préchargements d'atlas de texture. Voici un aperçu rapide de ce que je suis arrivé à ce jour:SpriteKit: Plantage étrange lors du préchargement des atlas de texture

GameViewController.swift

import UIKit 
import SpriteKit 

class GameViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Configure the view. 
     let skView = self.view as! SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 
     skView.showsDrawCount = true 
     skView.showsPhysics = false 
     skView.ignoresSiblingOrder = true 
     skView.multipleTouchEnabled = true 

     // Setup scene 
     let scene = GameScene(size: skView.bounds.size) 
     scene.scaleMode = .ResizeFill 

     let MyAtlas1 = SKTextureAtlas(named: "MyAtlas1") 
     let MyAtlas2 = SKTextureAtlas(named: "MyAtlas2") 
     let MyAtlas3 = SKTextureAtlas(named: "MyAtlas3") 

     SKTextureAtlas.preloadTextureAtlases([MyAtlas1, MyAtlas2, MyAtlas3], withCompletionHandler: 
     { 
      print("Everything loaded!") 

      // Present scene 
      skView.presentScene(scene) 
     }) 
    } 
    [...] 

GameScene.swift

import SpriteKit 

class GameScene: SKScene { 

    var cam: SKCameraNode! 
    var tilemap: Tilemap! 
    var previousTime: CFTimeInterval = 0 
    [...] 

    override func didMoveToView(view: SKView) { 
     /* Setup your scene here */ 

     [...] 

     // Setup camera 
     self.cam = SKCameraNode() 
     self.cam.setScale(self.camScaleFactor) 
     self.camera = self.cam 
     self.addChild(self.cam) 

     [...] 

     // Load Tilemap 
     self.tilemap = Tilemap(mapName: "testlevel2") 
     self.addChild(self.tilemap) 

     // Setup UI 
     [...] 
    } 

    [...] 

    override func update(currentTime: CFTimeInterval) { 
     /* Called before each frame is rendered */ 

     if self.previousTime == 0 { 
      self.previousTime = currentTime 
     } 

     let delta = currentTime - self.previousTime 

     var p = self.cam.position 
     p.x += 2.0 * CGFloat(delta) 
     p.y += 1.5 * CGFloat(delta) 
     self.cam.position = p 

     // Update tilemap 
     self.tilemap.update(delta) 

     self.previousTime = currentTime 
    } 
} 

La fonction didMoveToView est un peu long, comme initialise une caméra, un tilemap, une interface utilisateur et quelques contraintes. Cependant, cela compile bien. Mais quand je lance le jeu, il se bloque immédiatement avec l'erreur fatale suivante: "trouvé de manière inattendue nil lors du déballage d'une valeur optionnelle". Comme il se trouve, cette valeur est en option (de façon aléatoire) soit self.tilemap ou self.cam et l'erreur se produit dans la mise à jour() la fonction de GameScene sur l'une des lignes suivantes (également, au hasard):

// here 
var p = self.cam.position 

// or here 
self.tilemap.update(delta) 

Le débogueur me dit que self.tilemap ou self.cam est nul. Mais je ne peux pas comprendre pourquoi c'est le cas. Il me semble que la fonction didMoveToView est exécutée quand la scène est présentée, puis soudainement à mi-chemin, la fonction de mise à jour est appelée où self.tilemap ou self.cam n'est toujours pas initialisé.

Lorsque je change la fonction viewDidLoad du GameViewController à ceci:

override func viewDidLoad() { 
     super.viewDidLoad() 

     // Configure the view. 
     let skView = self.view as! SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 
     skView.showsDrawCount = true 
     skView.showsPhysics = false 
     skView.ignoresSiblingOrder = true 
     skView.multipleTouchEnabled = true 

     // Setup scene 
     let scene = GameScene(size: skView.bounds.size) 
     scene.scaleMode = .ResizeFill 

     let MyAtlas1 = SKTextureAtlas(named: "MyAtlas1") 
     let MyAtlas2 = SKTextureAtlas(named: "MyAtlas2") 
     let MyAtlas3 = SKTextureAtlas(named: "MyAtlas3") 

     SKTextureAtlas.preloadTextureAtlases([MyAtlas1, MyAtlas2, MyAtlas3], withCompletionHandler: 
     { 
      print("Everything loaded!")     
     }) 

     // Present scene 
     skView.presentScene(scene) 
    } 
    [...] 

tout fonctionne parfaitement. Mais ce n'est évidemment pas la solution, car je veux précharger tout avant en commençant la scène. Notez également: Je suis conscient que les atlas préchargés sont immédiatement effacés de la mémoire, car je n'y fais pas référence. Quoi qu'il en soit, ce code est vraiment juste pour la démonstration et les tests. Donc, ma question est la suivante: Quelqu'un at-il déjà eu un problème similaire ou sait ce qui se passe avec cette erreur? Je ne peux pas comprendre ce que je fais mal. Toute aide est très appréciée.

+0

Si vous regardez sur la console, il devrait vous dire quelle est la variable qui est nulle afin que vous ne deviniez pas. Aussi, pourquoi chargez-vous vos atlas dans le contrôleur de vue?Chargez-les dans le GameScene – Knight0fDragon

+0

Je n'ai pas deviné. Comme je l'ai dit, c'est soit au hasard self.tilemap ou self.cam. Quel est l'avantage de charger des atlas dans GameScene au lieu de les charger dans le ViewController? – snorge

+0

La lisibilité du code, les contrôleurs de vue ne devraient rien savoir des atlas, le GameScene le fait, alors 6 mois plus tard, vous choisissez ce code, vous ne vous demandez pas où vous mettez ces atlas. Et le code ne peut pas aléatoirement mettre à jour sans terminer didMoveToView, ils sont sur le même thread, donc quelque chose d'autre se passe dans votre code que nous ne connaissons pas – Knight0fDragon

Répondre

0

attach image ho setup SKView for UIView

Vous créez l'application en utilisant le modèle, il va créer vue comme SCNView. Ce SCNView entrer en collision avec vous désir d'avoir sur le panneau d'histoire SKView.

  1. Supprimer SCNView de votre story-board
  2. SKView n'est pas disponible comme option Afficher
  3. Entrez régulièrement UIView à story-board
  4. En classe de propriétés, le type SKView, il acceptera même il n'est pas sur la liste
  5. Cela va résoudre le problème lorsque vous essayez de créer SKView

Voir image jointe.