HDS#06 WorldLocationの罠

 

こんにちは、開発Gの杉原です。

 

もうすぐ4月。

4月といえば、4月1日のエイプリルフール。

毎年多くの企業でエイプリルフール企画がWEB上で行われているのですが、結構それを見るのが楽しみだったりします。

 

さて【How to Demo3D Scripting】の第6回は「WorldLocationの罠」をお送りします。

登場人物

デモス

Demo3Dワールドを牛耳るDemo3Dの生きる伝説(自称)。

決して宇宙怪獣の類ではない。

リディ

Demo3Dワールド連邦政府の議長の息子だが、Demo3Dについては素人。

さすがにロボットには乗らない。


「あー忙しい忙しい。新たな伝説を生み出すのって大変だなぁ」

ぴこーんぴこーんぴこーんぴこーんぴこーんぴこーん(なんかサイレン的な音)

「よりによってこんな時にDemo3DワールドにSOSが!?」

「デモえもん、助けてー。WorldLocationを変更してるのにモデルが動かないよー」

「元凶はお前か。なんだどういうことだソースを見せろ」

「これがソースです」

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    for (var i = 0; i < 30; i++) {
        sender.WorldLocation.X = i;
        wait(1);
    }
}
[Auto]
IEnumerable OnInitialize( BoxVisual sender )
{
    for (int i = 0; i < 30; i++) {
        sender.WorldLocation.X = i;
        yield return Wait.ForSeconds(10);
        }
}

「これはモデルが実行されてから、1秒おきにX方向へ1メートルずつ移動する、ということでいいか?」

「はい。ところが実行しても全然動かないんです。なんとかしてください」

「仕方がないな、ほら」

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    for (var i = 0; i < 30; i++) {
        sender.WorldLocationX = i;
        wait(1);
    }
}
[Auto]
IEnumerable OnInitialize( BoxVisual sender )
{
    for (int i = 0; i < 30; i++) {
        sender.WorldLocationX = i;
        yield return Wait.ForSeconds(10);
        }
}

「ちょっと、ふざけないでくださいよ。全然変わってないじゃないですか!」

「変わってない? お前の目は節穴か。よく見ろ」

Before:

sender.WorldLocation.X = i;

 

After

sender.WorldLocationX = i;

「いや、どっちも同じ……あっ、"WorldLocation"と"X"の間のピリオドがなくなってる?」

「その通り。WorldLocationプロパティのXプロパティを変更するのではなく、WorldLocationXプロパティを変更することで、今回の不具合を修正することができるんだ」

「でもどっちもワールド座標系のX座標を表す値ですよね? どうして違いが出るんですか?」

「"sender.WorldLocation.X = i;"というコードは、WorldLocationプロパティから取得されたオブジェクトのXプロパティを変更しているのに対し、"sender.WorldLocationX = i;"はWorldLocationXプロパティを変更している、というのはわかるな?」

「えっと……こういうことですか?」

「そう。だからWorldLocationXプロパティを変更すると、内部的に位置情報を変更する処理が行われて位置が変わるのだが、WorldLocationプロパティを取得してからXプロパティを変更しても、内部的な位置情報が変わらないというわけだ」

「なるほど……って、内部的な位置情報? WorldLocationとは別で位置情報を持ってるってことですか?」

「WorldLocationのほかに、Location、RelativeLocationといったVisualの位置を表すプロパティがあるだろ?」

「親Visualからの相対的な座標ですよね? それがどうかしたんですか?」

「WorldLocationを変更したらRelativeLocationも変わる。そしてその逆もまた同様だ。だからVisual型では基本の位置情報を内部的に持っていて、WorldLocationを要求されたらワールド座標系に変換し、RelativeLocationを要求されたら親のローカル座標系に変換しているんだ」

「つまり、取得される値は変換された値であって、基本の位置情報そのものじゃないから、取得した値を変更しても反映されないってこと?」

「そう。そしてこれはWorldLocation、というかVisual型に限らず、いろいろなオブジェクトで起こり得ることだ」

「むやみにプロパティのプロパティを変更しないほうがいい、ということですね」

(まあ、ちゃんと動くならよくやるんだけど)

 

はい。

というわけで、ありがちな対話形式でのコント、もとい解説でした。

 

もともと「How to Demo3D Scripting」というタイトルは、とあるプログラミング教育番組だとか、とあるネットワーク入門サイトだとかに影響されて名付けていて、それらに倣ってこういうことをやりたくてつけたのです。

が、こんなふざけた内容書いていたら怒られそうなので、内容はまじめ書いていまして。

 

今回、ちょっと早いですがエイプリルフールを意識して試しにやってみました。怒られても知らないです。

次回からは元の感じに戻しますが、これがアリならまたやるかもしれません。

 

その次回なんですが、4週にわたってVector3の話をしてきましたが、ちょっと深いという上司からの意見を受けたので、また違ったことをご紹介しようかなと考えています。

 

あと最後に、このお話は実際にあった質問に基づくフィクションです。

こんなひどい奴らは社内には実在しません。たぶん。


 

次回の【How to Demo3D Scripting】は「乱数の生成」です。

更新は4/5(木)、ご期待ください。

 

なお、ついに記事のストックがなくなったため、更新日時や内容は余儀なく変更される可能性があります。

予告通りになるよう、がんばります。