いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

Unityでビルボードを作る!

 ちゃんとした定義は知りませんが、ゲームプログラミングの技術の中に「ビルボード」というのがあります。3Dのゲームで、例えば道ばたの木など、ちゃんとモデリング(PC上で立体として木を作る。幹、枝、場合によっては葉などのパーツもしっかり)したものをいちいち使っていては実行時のPCの負担が大変です。そこで板に木の絵を貼り付け、木の代わりに立てて、カメラの方を向かせることがあります。これをビルボードと言います。計算コストも段違いですし、単に景色としてならこれで十分なことも多いでしょう。計画中のゲームでこれを使おうと思って調べました。
 Unityでは、3Dの空間中に板を用意して絵を貼り付けるとこんな感じになります。
f:id:Inuosann:20210210011233p:plain:w200
赤が画面で右方向(x軸)、緑が上方向(y軸)、青が画面の向こう側向き(z軸)です。要するに寝転がった状態になってしまい、このままではビルボードになりません。
f:id:Inuosann:20210210005801p:plain:w200
↑こんな風に立ち上がって欲しいのです。しかも空間内を動く目標(今回の例ではボール)の方を向かせたいのです。今回紹介する方法は、気づいてみれば当たり前なのですが、できるまで結構大変でした。同じ苦労をしている人がいると思います。記録しておきます。

        GameObject inuo = GameObject.FindWithTag("Inuo");
        GameObject target = GameObject.FindWithTag("target");
        inuo.transform.LookAt(target.transform);//とりあえず足をターゲットに向かせる
        // 軸の周りに90度回転するQuaternionを作成
        var rot = Quaternion.AngleAxis(90f, inuo.transform.right);
        inuo.transform.rotation = rot * inuo.transform.rotation; // Quaternionを使って回転させる

Inuoは板のオブジェクトで、犬の写真が貼ってあります。LookAt()は、犬(が貼ってある板)に目標のオブジェクトを向かせる関数です。Unityに用意されています。しかし、これは元の状態(オブジェクト作成時の状態)のz軸方向、つまり足を目標に向かせる仕様なのです。そのため、LookAt()だけだと次のようになってしまいます。
f:id:Inuosann:20210210011904p:plain:w200
1枚目の写真が板の作成時のものですが、要するにこのとき足がz軸の正の向きを向いており、LookAt()関数はこの足を目標(ボール)に向けてしまうのです!!
inuo.transform.right には、空間の中で、元のx軸方向のベクトルが現在どちらを向いているか、それが格納されています。犬の写真の右肩方向とでも言いましょうか、それが現在空間内でどちらを向いているか、です。そのベクトルを軸として90°回せば犬は立ち上がるわけです。回すにはクォータ二オンを使います。
f:id:Inuosann:20210210013030p:plain:w300
ちょっと分かりづらいかも知れませんが、犬が貼り付けてある面がボールにまっすぐ向いています。
ビルボードを使おうとする人は必ず同じ問題に突き当たるはずです。これで解決、気持ちよく寝られます。

 ビルボードを表示するにはどうするか、音を出すにはどうするか、枚の絵の一部分をここに表示するには……、と1歩1歩は地味ですが、きれいなプログラムができ上がります。期限付きでギリギリで、となると辛いんでしょうが、趣味でやっている分にはこれほど楽しいことはなかなかありません。日々、達成感も味わえますし、でき上がったときの喜びは大変です。これだけ楽しめて、費用は書籍代くらい。コスパのよさもすごいです。