現在、SpriteKitを使用してiOS用のゲームを行っています。テクスチャアトラスのプリロードを実装しているときに奇妙なクラッシュが発生しました。ここで私はこれまで得たものの迅速な概要です:SpriteKit:テクスチャアトラスをプリロードするときに奇妙なクラッシュが発生する
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
}
}
didMoveToView機能はそれとして、少し長いですカメラ、タイルマップ、UIスタッフ、およびいくつかの制約を初期化します。しかし、これはうまくコンパイルされます。しかし、私がゲームを実行すると、すぐに次の致命的なエラーでクラッシュします。「オプション値をアンラッピングしている間に予期せず見つからない」それは、(ランダムに)任意の値であることが、判明self.tilemap又はself.camとエラーは、次の行のいずれかにGameSceneの更新()関数(また、ランダムに)に起こるような:
// here
var p = self.cam.position
// or here
self.tilemap.update(delta)
デバッガは、self.tilemapまたはself.camがnilであることを通知します。しかし、私はなぜそれが当てはまるのか理解できません。シーンが表示されてから途中で突然途切れると、関数didMoveToViewが実行され、self.tilemapまたはself.camがまだ初期化されていないupdate関数が呼び出されます。
私はこれにGameViewControllerののviewDidLoad機能を変更します。
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)
}
[...]
すべてが完璧に動作します。しかし、それは明らかに解決策ではありません。を事前にロードしてから、のシーンを開始します。また注意してください:プリロードされたアトラスは、私がそれらを強く参照していないので、すぐにメモリから削除されることを認識しています。とにかく、そのコードはデモンストレーションとテストのためのものです。
私の質問は次のとおりです。誰も似たような問題を抱えていたことがありますか、そのエラーで何が起こっているのですか?私は何が間違っているのか分かりません。どんな助けも大歓迎です。
コンソールを見ると、推測されていないように変数が何であるかがわかります。また、なぜあなたのアトラスをView Controllerにロードしていますか?GameScene – Knight0fDragon
私は推測しませんでした。私が言ったように、それは無作為にself.tilemapかself.camです。 ViewControllerで読み込むのではなく、GameSceneの読み込みの利点は何ですか? – snorge
コードの読みやすさ、Viewコントローラはアトラスについて何も知ってはいけません、GameSceneはそうしていますので、6ヶ月後にこのコードをバックアップすると、あなたはそれらのアトラスをどこに置くのか不思議ではありません。そして、コードはdidMoveToViewを終了することなくランダムに更新することはできません。同じスレッド上にあるので、わからないコードで何かが起きています – Knight0fDragon