Progression FrameworkのForLoopとDoTweenerで、ウッヒョーイエー!ダーイ(Die)!
そんな訳でProgression Frameworkの話。つか、何で俺だけこんなに沢山の問題にぶち当たるのだろうか?やはり開発スタイル間違ってるのか?
さて今回は、ForLoopコマンドでDoTweener実行しようとしたらスタックオーバーフローで死ぬって話。
■問題と原因
この理由は案外簡単で、実はForLoop使わなくても、多分DoTweener再利用しようとしたら発生すると思う。
原因になってる、DoTweenerのコードはこの部分。
* @inheritDoc
* @langversion 3.0
* @playerversion Flash 9.0.45.0
*//*=======================================================================*/
protected override function _executeProgress():void {
// 既存のイベントハンドラメソッドを保存する
_onCompleteFunction = tweeningParameters.onComplete;//・・・・・・・(1)-1
// イベントハンドラメソッドを登録する
tweeningParameters.onComplete = _onComplete;//・・・・・・・(1)-2
// アニメーションを開始する
if ( !Tweener.addTween( _target, _tweeningParameters ) ) {
// 処理を終了する
_executeComplete();
}
}
/*======================================================================*//**
*
* @langversion 3.0
* @playerversion Flash 9.0.45.0
*//*=======================================================================*/
private function _onComplete():void {
// Tweener に設定されていた onComplete() メソッドを実行する
if ( _onCompleteFunction is Function ) {
_onCompleteFunction.apply( null );//・・・・・・・(2)
}
// 処理を終了する
_executeComplete();
}
(1)と(2)は俺が入れたんだけど、この2箇所のコードがポイント。
処理の流れを追うと、
- DoTweenerコマンドが始まると、元々Tweenerに渡す予定だった
onComplete関数を_onCompleteFunctionに退避して((1)-1)、 - 代わりにDoTweenerの終了処理に入れてる((1)-2)。
こうする事で、Tweenerの処理が終わった後呼ばれるのが、DoTweenerコマンドで定義されてる_onComplete()になる。
で、
- DoTweenerの終了処理で、
_onComplete関数が呼ばれる。 _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。
でまぁ、DoTweenerの処理は滞りなく終了するわけだけど、ここで大きな異変が。
(1)-2の部分で、Tweener用のパラメータが最初とは違うものになっちゃってる。わけです。
具体的に言うとonComplete。こいつが_onComplete関数になっちゃってるから、次にもう一回このDoTweenerコマンドを使うとどうなるか?
処理の流れを追うと、
- DoTweenerコマンドが始まると、元々Tweenerに渡す予定だった
onComplete関数を_onCompleteFunctionに退避して((1)-1)、 - 代わりにDoTweenerの終了処理に入れてる((1)-2)。
- DoTweenerの終了処理で、
_onComplete関数が呼ばれる。 _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。- が、2回目の「元々の終了処理」は
_onComplete関数であるため、_onComplete関数が実行される。 _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。_onCompleteFunction関数である、_onComplete関数が実行される。_onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。_onCompleteFunction関数である、_onComplete関数が実行される。
・・・
こんな感じで無限に_onComplete()が呼ばれ続け、最終的にはスタックオーバーフローで終了。
■解決策
DoTweener#_onCompleteを以下のように修正。
// Tweener に設定されていた onComplete() メソッドを実行する
if ( _onCompleteFunction is Function ) {
_onCompleteFunction.apply( null );
}
//onCompleteを元に戻す。
tweeningParameters.onComplete = _onCompleteFunction;
_onCompleteFunction = null;
// 処理を終了する
_executeComplete();
}
要するに、「終了時には元に戻しましょう」ということでいいと思う。でも成功確認しかしてないけど。




