プロジェクターで遊ぶ1

完成品

私は動かしすぎて3D酔いしました。弱い方はご注意ください!

最初は上下方向のキー入力にも対応してましたが、あまりにも酔いがひどかったので削除しました。

Unity Web Player

Unity Web Player. Install now!
Unity Web Player. Install now! Restart your browser after install.

« created with Unity »

前置き

 無料版では影機能はありませんが Projector を利用した手法があるようなので試してみました。
 色々触ってみましたがある条件下で上手くいかないようなので回避策を講じてみました。

下準備

 メニューから Assets > Import Package > Projectors を選択します。
 Import します。
 Assets 以下に右のように色々なデータが追加され使用できるようになります。
 今回は図では上から2番目の Blob Shadow Projector を使用します。

サンプル

 床の上にオブジェクトを置いても距離感が掴めません。
 影がつくと距離感を把握することが出来るようになります。
 

問題点

 オブジェクトの移動に影を追従させるために右図のように、オブジェクトの中に影を入れます。
 静止しているなら問題はありませんが通常オブジェクトは移動します。
 移動のみ問題ありませんが、回転が絡むと問題が発生します。
 右図のようにオブジェクトの回転に合わせて影も回転してしまいます。

回避策

 今回はスポットライトを使うので右図のような方法で回避したいと思います。

光源

 Spotlight です。
 位置や方向は好みでかまいません。

プレハブ作成

 まずはプレハブを作っていきます。
 右のような Hierarchy を用意しました。
 Floor は Cube を広げたものです。
 Cube 用に Physic Material を作りました。
 Cube はこんな感じです。
 Box Collider の Material に先ほど作成した Physic Material を適用しておきます。
 あとはデフォルトのままです。
 位置や回転は何でもかまいませんが Projector の調整が楽なので0や整数にしておくのがよいでしょう。
 Projector です。
 位置や方向はスクリプトで計算するのでテスト用に Cube からの距離を確認する程度で大丈夫でしょう。
 ここで大切なのは FarClip Plane と Field Of View の値です。
 右図のように光源に近づいた場合と離れた場合の影の具合が素敵になるような調整は難しいです。
 近づいた時濃すぎるなら Far Clip Plane を下げて、離れた時に影を広げたければ Field Of View を上げるとよいです。
 以上で量産型が完成したので最後に Assets へドロップして Prefab にしておきます。
 階層化してあるので右図のようになります。

テスト1

 テストプレイとして少しひねって落としてみました。
 光源の後ろにカメラを置いて光源の向きとカメラの向きを同じにしています。
 光と影が矛盾しているはずなのに矛盾していないように見えるのが不思議ですが、矛盾しているのでスクリプトを書いていきます。

スクリプト

 まずはスクリプトファイルを作成して Prefab へ放り込みます。

型宣言・・・

//Error!!
Vector3 spotLight;
Transform projector;
 上のような記述しかしてこなかったので型エラーでかなりさまよいました。
 下のように記述するのが正しいようです。
//Correct!!
var spotLight : Vector3;
var projector : Transform;
 光源は座標しか使わないので Vector3 型で宣言します。
 プロジェクターはTransform属性しか使用しないので Transform 型で宣言します。

初期化

function Start () {
  spotLight = GameObject.Find("Spotlight Name").transform.position;
  projector = transform.Find("Projector Name");
}
 双方 UpDate() で変化しないので Start() 内で取得しています。

位置補正

function Update () {
  //calc vector from cube to the light
  var vecLO = spotLight - this.transform.position;
  vecLO.Normalize();
  //calc and set position of projector
  projector.transform.position = vecLO * k + this.transform.position;
}
 Object の O としたのですが、原点も O で混乱してしまうことに今頃気がつきました。
 標準化ベクトルしか使わないので .Normalize() しています。
 オブジェクトとプロジェクターの距離は k で決まります。
 テストプレイをすると転がっているけれど、プロジェクターは光源とオブジェクトを結んだ直線状に存在しているのが確認できます。

向き補正

  //look at object
  projector.LookAt(this.transform.position);
 最後にプロジェクターを箱の方向を向くようにしてあげて完成です。
 上下左右で影の向きが微妙に変化しているのが確認できると思います。