VRエンジン作成日記

ひたすらVRエンジンを作っていきます

親子関係にあるオブジェクトの座標

今日は画面に表示されるオブジェクトの親子関係の座標についての実装を変更していた。今まではObject3Dというクラスに座標を格納していて、positionというメンバ変数に保存していた。座標を変えたい場合は次のように書く。

obj.position.x = 10;

こうすると、X座標が10のところにオブジェクトが移動する。

ただ、親子関係がある場合は安直に座標を入れ込むことができなくなる。例えば戦車のオブジェクトがあるとすれば、本体と砲台は一緒に動いた方がいい。また、戦車の本体が動いたら砲台は動かさなくても自動的にくっついていた方が便利だろう。そうする場合、戦車本体を親オブジェクトとして、砲台を本体の子オブジェクトというように関係を作っておく。自分で描画エンジンを書く場合は、この親子関係についても実装する必要がある。

Unityでは自分自身の座標はlocalPositionというメンバ変数に保存するようになっていて、親子関係を考慮した座標はpositionというメンバ変数に保存されている。具体的な実装ではどうなっているかというと、おそらくposition側はgetter/setterを通してアクセスする仕組みになっているだろうと考えられる。getter/setterがあると、副次的な操作を変数の参照時に加えることができる。また、position.xのようなさらに細かい参照については変更が伝搬しないようになっている。positionを変える場合はposition = newPositionというように書かなければならない。これはgetter/setterの動きがpositionのみに設定されていて、より細かい操作は上位オブジェクトに伝搬しないように設計されているためだろう。より細かい操作をサポートする場合は、JavaScriptでいうところのEventEmitter等を使ってposition.x等の要素の操作があった場合は、そこでemitする必要がある。ただ、そんなに細かい操作でemitが入るような仕組みは簡単に処理が重くなってしまうだろう。この設計は便利ではないが、速度と便利さのトレードオフとしてあえてそうしていると考えるのが自然だ。それらを考慮すると、JavaScriptでも同じようにしていればUnityユーザには分かりやすいだろうと思う。今日書いたコードでは、なんとなくそうなりそうな感じに書いておいた。不都合があれば後で修正する。

あと、コーディングレベルで気を付けないといけないこととしては、いつ親から伝搬されたpositionの値を更新するかという問題がある。getter/setter内に都度更新するような処理を書いても良いけど、毎回、孫、ひ孫オブジェクトがルートまで登って行って座標を取得するというのはどう考えても処理時間がかかるだろうと予想が立つ。ただ、キャッシュするにしてもいつなのか、親が更新されたら子側全てを更新しておくというのが良いのか、ベストな解決方法というのはぱっと思い浮かばなかった。この辺も思いつき次第で修正しておきたいと思う。

・関連するコミット

fix some functions · hikipuro/tea.js@ef582ef · GitHub