動的生成したオブジェクトはインスタンス名で参照できない

例えば、次のようにMovieClipを動的に階層化する。

var target_mc:MovieClip = new MovieClip();
this.addChild(target_mc)

var img_mc_on:MovieClip = new MovieClip();
var img_mc_off:MovieClip = new MovieClip();

target_mc.addChild(img_mc_on);
target_mc.addChild(img_mc_off);

これを

trace(“target_mc.img_mc_off”,target_mc.img_mc_off,target_mc.img_mc_off.name)

とすると、下記のようにエラーになる。

TypeError: Error #1010: 条件は未定義であり、プロパティがありません。

「ああ、インスタンス名をつけておかないといけないのか」と、下記のように変更しても同じエラーが出る。

var target_mc:MovieClip = new MovieClip();
this.addChild(target_mc)

var img_mc_on:MovieClip = new MovieClip();
var img_mc_off:MovieClip = new MovieClip();

img_mc_on.name = “img_mc_on”;
img_mc_off.name = “img_mc_off”;

target_mc.addChild(img_mc_on);
target_mc.addChild(img_mc_off);

trace(“target_mc.img_mc_off”,target_mc.img_mc_off,target_mc.img_mc_off.name)

「何で???」と悩んでいたら、下記のサイトを発見。
要は「動的に生成したインスタンスは、インスタンス名で参照できないので、addChildしたオブジェクトのプロパティにインスタンス本体を入れておく」必要があるらしい。で、次のように改訂。

var target_mc:MovieClip = new MovieClip();
this.addChild(target_mc)

var img_mc_on:MovieClip = new MovieClip();
var img_mc_off:MovieClip = new MovieClip();

img_mc_on.name = “img_mc_on”;
img_mc_off.name = “img_mc_off”;

target_mc.addChild(img_mc_on);
target_mc.addChild(img_mc_off);

//これが重要!!!
//動的に生成したインスタンスは、インスタンス名で参照できないので
//addChildしたオブジェクトのプロパティにインスタンス本体を入れておく。
target_mc[“img_mc_on”] = img_mc_on;
target_mc[“img_mc_off”] = img_mc_off;

trace(“target_mc.img_mc_off”,target_mc.img_mc_off,target_mc.img_mc_off.name)

これで下記のように正しく参照されてることが確認できます。

target_mc.img_mc_off [object MovieClip] img_mc_off

ちなみにnameを設定しない場合には、下記のようになります。

target_mc.img_mc_off [object MovieClip] instance3

オーサリングでステージ上に作成したオブジェクトは、AS2.0までと同じく使えるのでわかりにくいですね。
上記F-siteの記事によれば『前述「オーサリング時に配置したMovieClipインスタンス』では、タイムラインに予め配置して[プロパティ]インスペクタで設定したインスタンス名は、そのまま変数のように参照として扱うことができました。これは、ActionScript 3.0では、Flashがインスタンス名と同じ名前の変数を自動的に宣言して、そこにインスタンスの参照を格納する仕組みになっているからです」ということらしい。う〜ん。こういうことは実際に遭遇してみないと気づかないですね。
でも最初に作ったtarget_mcが問題なく参照されているのは何でだろう?推察するに、ステージ(タイムライン)上に生成したオブジェクトは、オーサリング時に配置したオブジェクトと同様に自動的に処理されるってことなんでしょうね。
<追記>2010.8.18
最後の「でも最初に作ったtarget_mcが問題なく参照されているのは何でだろう?」については、野中さんから「参照には変数に設定されている必要がある」というご指摘いただきました。詳しくはコメント欄を参照のこと。

「動的生成したオブジェクトはインスタンス名で参照できない」への6件のフィードバック

  1. > でも最初に作ったtarget_mcが問題なく参照されているのは何でだろう?
    _____
    タイムラインにvar宣言された変数だからです(インスタンス名ではありません)。img_mc_onやimg_mc_offも同じです。けれども、target_mc上に宣言されてはいませんから、target_mcを参照してアクセスすればエラーになります。

  2. >野中さん
    コメントありがとうございます。
    直接・・・
    target_mc.img_mc_on = new MovieClip();
    とすれば、問題ないということですね。ステージ上に作ってから、target_mcにaddChildしているのが問題であると。

  3. MovieClipインスタンスの生成ではなく、あくまで変数のあるなしが問題です。img_mc_onを当該タイムラインではなく、target_mcの変数として設定することが必要です。
    var target_mc:MovieClip = new MovieClip();
    this.addChild(target_mc);
    var img_mc_on:MovieClip = new MovieClip();
    target_mc.addChild(img_mc_on);
    target_mc.img_mc_on = img_mc_on; // 変数を追加
    trace(“target_mc.img_mc_on”,target_mc.img_mc_on,target_mc.img_mc_on.name);

  4. つまり…
    target_mc.img_mc_on = img_mc_on; // 変数を追加
    は、生成後に変数に追加していて
    target_mc.img_mc_on = new MovieClip();
    は、インスタンスの生成と変数への追加を一度にやっているということですね。
    どちらも変数に追加しているので、参照可能であると。

  5. そうですね。
    ちなみに、最初の例はタイムラインとMovieClipインスタンス(target_mc)の双方に同盟の変数(img_mc_on)が存在し、同じインスタンスを参照していることになります。

  6. >野中さん
    やっと理解できました。ありがとうございます〜。

コメントは停止中です。