ガーベッジコレクションを実感してみる
Tweenerが業界標準的存在なのでめっきり使わなくなったfl.transitions.Tween(AS2.0ではmx.transitions.Tween)クラス。これを使って途中でトゥイーンが止まってしまう現象があったので調べていると原因はガーベッジコレクションであることがわかりました。
そこで実証サンプルを作ってみました。途中で参照が断ち切られ、トゥイーンが止まる事が実感できると思います。
サンプルは以下から。
ガーベッジコレクションのサンプル
http://clockmaker.jp/labs/080627_gc_tween/main.swf
ガーベッジコレクションの監視はGCWatcher:GCの起動とオブジェクトの回収状況を監視するための方法 - プログラミングとかそんなのから拝借しました。ありがとうございます。
どうでしょう?10秒ほど時間がたつと参照が断ち切られアニメーションが途切れてしまうのが確認できると思います。System.gc()ボタンはそのメソッドを行うボタンで、それを押した瞬間にも参照が断ち切られるのが分かると思います。
問題になっているスクリプト部分
ローカル変数(雪のDisplayObject)をTweenに指定しているのがまずいんですね。
※ちなみにTweeerに書き直したら問題はありませんでした。
var snow:Sprite = new Snow(); //Snowはリンケージ指定したMC snow.x = stage.stageWidth * Math.random(); addChild(snow); watcher.watch(snow); //watcherはGC監視インスタンス var tw:Tween = new Tween(snow,"y", Regular.easeIn, 0, stage.stageHeight, time, true); tw.addEventListener(TweenEvent.MOTION_FINISH, function(event:TweenEvent) { event.target.removeEventListener(TweenEvent.MOTION_FINISH, arguments.callee); removeChild(snow); });
つまりローカル変数は一定時間後にGCが起動した際に参照が断ち切られるので、Tweenを行っている間に参照が消えるとアニメーションさせようにも対象のインスタンスを取得できずモーションが止まってしまうのです。ローカル変数でなくクラス変数やタイムライン変数、もしくはどこかに参照を保存しておけば問題ないのですが、気をつけないといけないですね。AS2ではこの書き方で問題なく動いており、AS3だとつまずいたので言語を移行する人は注意が必要です。
ガーベッジコレクションは数年前に存在を知り、最近はてなで話題に上がる事が増えましたが、イマイチその事象で困ることがありませんでした。このサンプルを試して実感が一つわきました。