質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
SpriteKit

SpriteKitは、iOSやOS Xで使用できるApple社製の2Dゲーム開発フレームワークです。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

3回答

7557閲覧

[Swift3/SpriteKit]コンソールにmemory issueエラーメッセージが出る

tossymotion

総合スコア22

SpriteKit

SpriteKitは、iOSやOS Xで使用できるApple社製の2Dゲーム開発フレームワークです。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/03/15 17:51

編集2017/03/23 16:17

###前提・実現したいこと
xcode8 と swift3を使っています。
現在SwiftのSpriteKitを使って簡単な2Dグラフィック横スクロールゲームを作成しています。
ボールのプレイヤー、壁を配置し加速度センサーを使用して
壁に当たらないようにプレイヤーをスタートからゴールへとコントロールする
ゲーム内容です。
ステージは今の所1から4まで作成しました。
ステージ4をクリアしたらゲーム終了です。

###問題
ゲームを進めていきステージ1〜3までは問題なくシーンが推移表示されるのですが
ステージ3から4へシーンを推移する時だけコンソールに下記のエラーメッセージが出てアプリがクラッシュしてしまいます。

Message from debugger: Terminated due to memory issue

メモリーに関するエラーのようなのですが具体的にどうすればいいのか
分からず困っています。
どのような原因が考えられますでしょうか。
どうぞよろしくお願いいたします。

###試したこと
GameViewController.swiftの一番初めに表示するSceneを
ステージ1からではなくステージ4からにすると問題なく表示されました。
しかしステージ1から進めていくとやはりステージ3から4の間でエラーが出ます。
ちなみにremoveallchildrenをコード内に入れてません。
(追記)
その後MemoryのモニタリングをしていたところSceneを描画するたびに
Memoryの数値が上がっていきステージ4を描画する頃には600MBを超えており
その拍子にアプリがクラッシュしてしまうようです。
そこまでは分かったのですがどうすれば解決できるのかが分かりません。
コード内にremoveallchildrenを入れましたが変わらず。
根本的に何かが間違っているのでしょうか。
ご教授いただければ大変助かります。よろしくお願いいたします。

Swift

1import SpriteKit 2import CoreMotion 3 4class Stage1Scene: SKScene, SKPhysicsContactDelegate { 5 6 //衝突判定用のカテゴリー設定 7 struct ColliderType { 8 static let player_cat: UInt32 = ( 1 << 0) 9 static let pipe_cat: UInt32 = ( 1 << 1) 10 static let goal_cat: UInt32 = ( 1 << 2) 11 } 12 13 //motionManager生成 14 var motionManager: CMMotionManager! 15 16 //プレイヤー変数宣言 17 var player = SKSpriteNode(imageNamed: "metal") 18 var playerXposition: Double = 0 19 var playerYposition: Double = 0 20 21 //カメラノード宣言 22 var cameraNode: SKCameraNode! 23 24//起動時処理 25 override func didMove(to view: SKView) { 26 self.physicsWorld.gravity = CGVector.zero 27 self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame) 28 self.physicsWorld.contactDelegate = self 29 30 motionManager = CMMotionManager() 31 motionManager.accelerometerUpdateInterval = 0.1 32 motionManager.startAccelerometerUpdates(to: OperationQueue.main,withHandler: {(accelerometerData:CMAccelerometerData?, error:Error?) -> Void in 33 34 35 self.playerXposition = accelerometerData!.acceleration.y * 20 36 self.playerYposition = accelerometerData!.acceleration.x * -20 37 }) 38 39 cameraNode = childNode(withName: "cameraNode") as? SKCameraNode 40 let zoomIn = SKAction.scale(to: 0.2, duration: 0) 41 cameraNode.run(zoomIn) 42} 43 44 //タッチ開始時 45 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 46 for touch: AnyObject in touches { 47 let location = touch.location(in: self) 48 let touchedNode = self.atPoint(location) 49 50 if (touchedNode == nextSprite) { 51 52 self.isPaused = false 53 label.text = "" 54 55 self.removeAllChildren() 56 //ステージ2へのシーンの推移 57 let scene = Stage2Scene(fileNamed: "Stage2Scene") 58 let transition = SKTransition.fade(with: UIColor.white, duration: 2.0) 59 scene?.scaleMode = SKSceneScaleMode.aspectFill 60 self.view?.presentScene(scene!, transition: transition) 61 62 //全てのスプライトを削除 63 self.removeAllChildren() 64 self.removeAllActions() 65 66 } 67

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/03/15 23:38

ステージ3から始めるとどうなるでしょうか?
fuzzball

2017/03/15 23:44

デバッガやprintを駆使して、エラーが発生する場所/原因を絞って下さい。その上で(まだ解決しないようなら)コードを追記して下さい。
tossymotion

2017/03/16 04:05

分かりました。試してみます!
fuzzball

2017/03/23 03:01

ステージ1の後もステージ1になるようにしても落ちますか?また、少しずつプログラムを削っていって原因を絞り込んで下さい。
tossymotion

2017/03/23 15:45

コメントありがとうございます。ステージ1→ステージ1→ステージ1と繰り返しScene遷移してもMemoryは157MBあたりで変わらず落ちませんでした。コードも見直してみます。
tossymotion

2017/03/23 16:21 編集

Scene遷移のタイミング(touchesBeganメソッド内)でremoveAllChildren()のあとにDispatchQueue.main.asyncAfter(deadline: .now() + 1.0)で少し時間を遅らせてからScene遷移を試してみました。Memoryを確認したところ一旦13MBまで落ちますがSceneが表示された時にやはりMemoryが増えますので、やはりScene生成時にメモリリークが発生していることを再認識しました。
fuzzball

2017/03/23 23:36 編集

リークというのは解放時に起こるものです。(解放漏れ=リーク)
tossymotion

2017/03/24 00:35

リークというのは解放時に起こるのですね。教えていただきありがとうございます。
fuzzball

2017/03/24 00:43

遷移開始時は今までのSceneが解放されて使用メモリが減る、遷移後は新しいSceneが生成されて使用メモリが増える、という正常な状態だと思いますが、そういう話ではないのでしょうか?
tossymotion

2017/03/24 01:10 編集

ステージ1,2,3,4それぞれで用意しているNodeの数は大体同じ、イラストのサイズも大体同じサイズを配置しています。ステージ1Sceneプレイ中ではMemoryの表示は大体43MB。そのあとremovefromchild()して13MBほどに落ちたあとステージ2Sceneが表示された後に本来ならば同じ43MBほどのMemory表示ならば良いのですが130MBほどに膨れ上がるのです。
fuzzball

2017/03/24 01:35 編集

「同じサイズ」というのはファイルサイズでしょうか?画像サイズでしょうか?ファイルサイズが異常に大きい画像はないでしょうか?130MBというのは何に確保されているか調べられるでしょうか? ステージ1でやったように、ステージ2〜4についても同じように繰り返し遷移するテストを出来るでしょうか?
tossymotion

2017/03/24 02:10 編集

説明不足申し訳ございません。「同じサイズ」というのは画像のファイルサイズのことになります。確かどれもファイルサイズは50KBほどだったと思うのですが遷移テストも後ほど併せて確認してみます。ご丁寧にありがとうございます。
tossymotion

2017/03/26 15:32

今回使用しているイラスト素材のファイルサイズはステージ1〜4まで全て合わせて50MBでした。特に大きいファイルサイズのイラスト素材は使用しておりません。
tossymotion

2017/04/01 17:58 編集

ステージ2〜4についても繰り返し遷移するテストを行ってみましたがMemoryの表示が増えていくことはありませんでした。メモリが何に確保されているかの確認はどう調べればいいのかが分かりません。あとdeinit{}でコンソールにprint出力の表示を確認しました。
fuzzball

2017/04/02 23:56 編集

同じステージを繰り返すテストのときもpresentScene()を使っていますか?これに限らず、テスト時と通常時の違いを探して下さい。
guest

回答3

0

ベストアンサー

80%くらい妄想です。

Sceneに紐付いているものはpresentScene()ときに解放されていると思うのですが、それ以外のものは解放されていないような気がします。例えば質問のコードで言うと、CMMotionManagerです。

まずは、CMMotionManagerを生成しないようにしてテストしてみて下さい。
それでエラーが出ないようであれば、CMMotionManagerの管理を上の階層(ViewController?)で行うように修正して下さい。

投稿2017/04/03 01:00

fuzzball

総合スコア16733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tossymotion

2017/04/06 08:08

ご回答ありがとうございます。 ご指摘いただいた通りSceneに紐づいているもの以外が解放されていないのかもしれません。 一度試してみます。 勉強不足なのに丁寧にご回答していただき本当にありがとうございます。
tossymotion

2017/08/04 06:13 編集

すみませんコメントが遅れましたが、その後確認したところご指摘の通りCMMotionManagerが 原因であることが判明しました。 Scene毎にCMMotionManagerのインスタンスが生成されていることが原因でした。 Sceneが遷移するタイミングでmotionaManger停止の命令を入れたところメモリーリークは 改善されました。Sceneが遷移するときに解放されるものだとばかり思いこんでおりました。 本当にありがとうございました。
guest

0

描画するたびにということであれば、その時にメモリリークをするようなコードになっているということでしょうね。

静的アナライザを利用したり、動的に解析されるのがよろしいかと。
https://developer.apple.com/jp/documentation/ToolsLanguages/Conceptual/Xcode_Overview/WritingCode/AnalyzingYourCode.html

https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/CommonMemoryProblems.html
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/FindingLeakedMemory.html

投稿2017/03/23 02:56

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tossymotion

2017/03/24 00:28 編集

お返事ありがとうございます。 InstrumentsのLeak Checksで調べたところやはりSceneから新しいSceneを遷移読み込むタイミングにメモリリークが起きているようです。 6 new leaks→Leaked ObjectはCGPathと出ております。
guest

0

Scene毎にCMMotionManagerのインスタンスが生成されていることが原因でした。
Sceneが遷移するタイミングでmotionaManger停止の命令を入れたところメモリーリークは
改善されました!

投稿2017/09/21 08:56

tossymotion

総合スコア22

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問