composerの移動時における消去、メモリ開放について

74 views
Skip to first unread message

cafe...@gmail.com

unread,
Feb 21, 2016, 8:00:38 AM2/21/16
to 日本コロナの会
はじめまして。
cafemasterと申します。
よろしくお願いいたします。

ご質問があります。
composerで、
A.lua、B.lua、C.luaがあり、それぞれをcomposer.gotoSceneで移動させた場合、
AとBの行き来は問題なくメモリ開放されてできるのですが、
CからBの移動がメモリが残ってしまいます。

Bは重力設定や衝突処理を行っているのですが、B→C→Bに移動させたとき、移動前Bの衝突情報が残ってしまいます。
AとBの行き来については全てがクリアされて最初のまっさらな状態でいけます。

それぞれの消去、メモリ開放はscene:hide( event )の"will"でcomposer.removeScene(””)で行っております。
C→B時のBの消去、メモリ開放ができない理由、考えられる原因を教えていただけないでしょうか?

C.C.

unread,
Feb 21, 2016, 8:20:38 AM2/21/16
to coro...@googlegroups.com
cafemaster さん、こんばんは CyberCatfish です。

えーと、それ、多分たまたまです (^^;;

デフォのまま A -> B -> C -> B と繊維させてみてください、多分その程度
の繊維だと destroy イベント発生していない(破棄されてない)はずです。
これは画面繊維効率を上げるためにライブラリが意図的に行っています。

もし画面繊維時にシーンそのものを破棄したい場合は、
1. コンポーザLIBに毎繊維時破棄させる
 > composer.recycleOnSceneChange
2. 明示的に破棄させる
 > composer.removeScene()
3. 自分でメモリを破棄する
 > hide イベントにて削除

などの処置が必要なはずです、ここ僕も結構悩みました (^_^!

cafe...@gmail.com

unread,
Feb 22, 2016, 9:15:21 AM2/22/16
to 日本コロナの会
CyberCatfishさん、返信ありがとうございます。
一応、
>2. 明示的に破棄させる
 > composer.removeScene()
>3. 自分でメモリを破棄する
 > hide イベントにて削除
は質問に書いてありますとおり行っています。

何度も試行錯誤しているのですが、メモリが残るというか、
具体的に言うと、変数がリセットされてなかったり、表示を消している衝突判定に衝突したとたんに動きが止まってしまいます(衝突判定のIFを満たしていないにもかかわらずです)。

デバッグで画面遷移を確認しているのですが、destroy やhideには移動しています。
ただ、変化がなかったのでdestroyには処理を入れていません。

何かヒントがあれば、ご教示よろしくお願いいたします。

C.C.

unread,
Feb 22, 2016, 1:19:25 PM2/22/16
to coro...@googlegroups.com
cafemaster さん、こんばんは CyberCatfish です。

えーっとですね、基本的な話として、Scene はすべて1つのテーブル
に格納されてます、変数どころかファンクションも含めて乗ってます。
もし、removeScene するなら、自シーン内ではなく、次のシーンに
移動してから前のシーンを削除する、だと思うのですが (^^;;

あと、作りが見えてないのでなんとも言えないのですが、消えていな
いという変数ですが、Scene テーブル内の変数ですか?
グローバルや他テーブルにぶら下げてしまった変数は、当然の事なが
ら消えません。

ただ、もし毎回消して良いのだぞというのであれば、シーン開始時に
きちんと初期化してしまえば問題は無いと思います。
僕は変数というより表示系がやっかいなので、毎回パージさせてしま
うように変数設定してしまっています (^_^!


全然関係無い愚痴を少し:
しかし Corona は内部の作りが見えづらくて難しい。
特に表示系の扱いがバラバラでwidgetなんて最悪、ネーティブ関連の
パーツの挙動が違いすぎて困ってます。
全部自分で作り直すハメになるんですが、フォント周りは lua からは
いじれなくて・・・シクシクシク、現在進行形で頭悩ませてます。

naoya yamamoto

unread,
Feb 23, 2016, 1:45:58 AM2/23/16
to 日本コロナの会
physics.stop()をscene:hide()の時に呼ぶのはどうでしょう。


山本

2016年2月23日 3:19 C.C. <cyberc...@gmail.com>:

--
--
このメールは次の Google グループの参加者に送られています: 日本コロナの会
このグループにメールで投稿: coro...@googlegroups.com
このグループから退会する: coronaja+u...@googlegroups.com
その他のオプションについては、次の URL からグループにアクセスしてくださ
い。 http://groups.google.co.jp/group/coronaja?hl=ja
--------------------------------------------------------------------------
http://twitter.com/JapanCoronaGrp

---
このメールは Google グループのグループ「日本コロナの会」の登録者に送られています。
このグループから退会し、グループからのメールの配信を停止するには coronaja+u...@googlegroups.com にメールを送信してください。
その他のオプションについては、https://groups.google.com/d/optout にアクセスしてください。

cafe...@gmail.com

unread,
Feb 23, 2016, 10:18:00 AM2/23/16
to 日本コロナの会
CyberCatfishさん
返信ありがとうございます。
グローバル変数は使っておらず、localをcreateで宣言してます。

山本さん
アドバイスありがとうございます。
physics.stop()はscene:hide()で使っていますが、
リンク先を確認したところ、removeSceneしてもinsertしていないものは消去されないということを思い出しました。
もう少し読み込んで研究してみます。

しかし、相変わらずB→C→Bで以前の情報が残っている状態です。
繊維は
B_create→B_show→B_show→B_hide→B_destroy→C_create→C_show→C_show→C_destroy→C_hide→B_create→B_show→B_show
です。

A→B→A→BではBの変数や状況がクリアされていますが、遷移を確認したところ、
B_hideを通っていませんでした。

ちなみにA→B→C→B→A→BだとBの変数や状況がクリアされます。

大変恐縮ではありますが、アドバイスや参考になるページがあればご教示ください。
よろしくお願いします。

C.C.

unread,
Feb 23, 2016, 12:47:41 PM2/23/16
to coro...@googlegroups.com
cafemaster さん、こんばんは CyberCatfish です。

がんばってますね、細かいことを言うようですが、画面繊維時には以下の
ようなイベントが呼ばれてるはずです。

Scene.A から Scene.B への繊維
  Scene.A > create
  Scene.A > show:will
  Scene.A > show:did
  Scene.A > hide:will
    Scene.B > create:
    Scene.B > show:will
  Scene.A > hide:did
    Scene.B > show:did
  Scene.A > destroy
  *fade指定するとhide/showが繰り返される事あり

ですから Scnese を Remove しようとしたら、次画面の show:did のタイ
ミングでという事になります。
ただ、少し書きましたが fade などで次画面の show/hide が複数呼ばれる
事があるので、元画面のテーブルが残存してれば削除するなどの状態わけ
を書く必要があります。

で、↑ これ毎回毎回意識して Destroy するの面倒じゃないですか。
もし毎回全てを捨てて良いとしたら、実は先に紹介した方法が一番簡単
だと思っています。

main.lua で composer を呼び出す前におまじない ↓ こんな感じ。
-- Start
composer.recycleOnSceneChange = true
composer.gotoScene("scene.home”)

これ API ドキュメントには存在が書いてあるものの、使い方書いてない
フラグなんですよねぇ、true にしとくと画面繊維で毎回 destroy を呼び
だしてメモリクリアしようとします。
毎回と書きましたが、Scnene.A -> Scnene.A と言ったような、パージで
きないパターンでは Destroy は呼ばれません。

これで一度、繊維状態を確認してみてください。
これでも消えてないとしたら、プログラム何処か間違ってます (^^;;

cafe...@gmail.com

unread,
Feb 24, 2016, 10:55:36 AM2/24/16
to 日本コロナの会
CyberCatfishさん
何度も返信ありがとうございます。
勉強させていただいてます。

いろいろと確認した結果、どうやら定義したdisplay.newGroup()が消えていなかったみたいです。
ただ、display.newGroup()を消してしまうと、attempt to perform arithmetic on field'x'(a nil value)エラーが出てきます。
それに対応しているRuntime:addEventListener( "enterFrame", enterFramew )をremoveしても同じエラーが出ます。

composerの動作とともに、coronasdkのHPでgoogle翻訳片手にちょっとエラーの消し方を勉強してみます。
アドバイスありがとうございました。

C.C.

unread,
Feb 24, 2016, 12:52:11 PM2/24/16
to coro...@googlegroups.com
cafemaster さん、こんばんは CyberCatfish です。

なんとなーく解決の糸口が見えたようで、頑張ってください(笑

多分最後になると思いますが、メモリ関連では ビュー範囲 と ライフ範囲 を
意識しながら書くか、パッケージ化して毎度意図しないでもきちんと消える
事を意識する必要あります。
lua では、殆どメモリ管理を考えないで書けるんですが、Corona SDK を使う
限り意識せざるをえない場面に出くわします、特に Display 関連 ( ToT)

先に山本さんが指摘された Physics 関連も同じです、アニメや衝突など判定
するためにタイマーやら画面やらにぶら下がっちゃうおかげで、シーンとい
う範囲には収まらないので、初期化や削除が別途必要になるということなの
で、やっぱり ビュー/ライフ範囲の意識になります。

幾つか残っているようですが、グループを消そうとした時にすでにグループ
がいなかったり、グループ消したつもりがぶら下がってるのいて消えてない
とか、下にいたオブジェクトがグローバルに付け変わってたりする事がある
と思います。
他にも、イベントリスナーを消すのはファンクションオブジェクト消滅前な
ので、オブジェクト消滅前に消す必要あるとか・・
  Scene.A > hide:will <- イベント消すなら最低でもこの辺
  Scene.A > hide:did <- オブジェクト消すのはこれ以降
  Scene.A > Destroy <- シーン関連を処分するのはこのあたり

この辺はロジカル的に設計していないとわかりにくいんですが、一々面倒だ
という場合はデバッガーで止めて、そのオブジェクトがどうなってるのか見
るのが一番手っ取り早いです。
最初はデバッグ自分で作ってたんですが、今は LuaGlider が手放せません (^^;;
イベント内で止めて、その変数とかがどうなってるのか見えます。
また、Profile 実行でグルグルまわしてやると、忘れてたオブジェクトが残存
してるのが見えたりして、お手軽に確認できます。

と、また長くなってしまいました orz
Reply all
Reply to author
Forward
0 new messages