こんにちは、開発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(木)、ご期待ください。
なお、ついに記事のストックがなくなったため、更新日時や内容は余儀なく変更される可能性があります。
予告通りになるよう、がんばります。
コメントをお書きください