この記事はUnity Advent Calendar 2019、13日目の記事です。
昨日は@Kan_Kikuchiさんによる、「誰でも簡単に使える最強のAudio(BGM, SE)Manager【Unity】」でした。
今回はUnityネタをやっていきます。
テーマは「鏡に映る3Dモデルを差し替える」です。
去年のアドベントカレンダーの派生になります。まだの方はこちらからチェック!
↑去年の記事を公開後、以下のような反応がありました。
(かなり前のツイートですが、この記事自体も去年に書き始めたものです)
鏡に映る姿だけ違うとか出来るとなお良し
— みそじゃが (@Misojaga) December 3, 2018
面白そうなアイデア!
アニメのOPでありそうな表現です。今回はこれを実現してみます。
開発環境
Unity 2019.3.0f
Magic Mirror Lite ver1.2.0
Unity2017.4.28f1
VRCSDK-2019.09.18.12.05_Public
※他2019.2f1、2018.4.11f1で動作確認済みです
アプローチ
今回どういう方法でやるかについて。
RealWorld(現実世界)とMirrorWorld(鏡の世界)の2つのレイヤーを作成。
CameraにはMirrorWorldは映らず、鏡にはRealWorldが映らないように、
それぞれのオブジェクトを各レイヤーに割り当てます。
やってることはとても簡単で、数回マウスをポチポチするだけでできます。
シーンの準備
最初にシーンを作っていきます。
キャラクターの用意
前回に引き続き、SDユニティちゃんとホラーちゃんを使用します。どちらも無料アセットです。
現実世界ではユニティちゃんがいて、鏡には怪物が映るといった感じです。
キャラクターは重なるように置いておきましょう。
ホラーちゃんは初期状態だと横を向いているので直したくなりますが、
アニメーションをするといつも通りになるのでそのままでOK。
ここはそれぞれ好きなキャラクターで大丈夫です。
キャラクターが用意できない方はCubeを使いましょう。
レイヤーを分ける
レイヤーの作成
Project Settings/Tags and Layersからレイヤーを分けていきます。
今回は「RealWorld」と「MirrorWorld」の2つのレイヤーを新たに作成しました。
オブジェクトのレイヤー設定
各オブジェクトのレイヤーを設定します。
ユニティちゃんは「RealWorld」、ホラーちゃんは「MirrorWorld」を設定します。
ちなみに、大量のオブジェクトをガッツリわけたい場合は、ルートのオブジェクトを作り、
子オブジェクトにしてあげると、一括変更も楽で管理しやすくなるのでオススメです。
親のレイヤーを変更すると、子もまとめて変更してくれます。
Cameraに映らないようにする
特定レイヤーのオブジェクトがCameraに映らないようにします。
これは簡単にできます。
CameraコンポーネントのCulling Maskから、描画するレイヤーを設定できます。
映したくないレイヤーはチェックボックスを外しましょう。
Everythingは全てのレイヤーにチェックを入れ、Nothingは全てのレイヤーのチェックを外します。
今回はMirrorWorldレイヤーをCameraに映らないようにしたいので、MirrorWorldのチェックを外します。
これでホラーちゃんはCameraに映らなくなりました。
ちなみにこちらのCulling Maskは各種Lightにも同じパラメータがあり、
レイヤーごとにDirectionalLight等を作成することでライティングを分けることもできます。
鏡を作る
鏡を作りましょう。Unityにおいて鏡を作る方法は複数あります。
前回のUnity Advent Calendar 2019 #3 11日目の記事にて紹介した無料アセット「Magic Mirror Lite」と
「MirrorReflection」「VRCSDKの鏡」の3つで動作確認をしています。
鏡に映るレイヤーを制限する
そのままだと鏡には全てのオブジェクトが映ります。
これに制限を加え「RealWorld」レイヤーのオブジェクトだけ映らないようにします。
やり方はCurring Maskのチェックを外すだけです。(鏡によって多少パラメータ名が違うかもしれません)
Magic Mirror Liteで鏡を作る場合
アセットをインポート後、Assets/MagicMirror/Prefab/Mirror.prefabを設置。
Mirror ScriptコンポーネントのRefrect Layersからチェックを外しておきます。
MirrorReflectionで鏡を作る場合
こちらを参考にマテリアルとスクリプトを用意します。コピペするだけです。
それらをPlaneにアタッチして、Mirror ReflectionコンポーネントのReflection Layersから、
RealWorldのチェックを外します。
VRCSDKの鏡を使う場合
SDKのunitypackageをインポート後、
Assets/VRCSDK/Prefabs/World/VRCMirror.prefabをシーンに配置します。
VRC_Mirrior_ReflectionコンポーネントのReflect LayersからRealWorldのチェックを外します。
完成品
これで完成です。
鏡に映る3Dモデルを無事差し替えることができました。
「やあユニティちゃん・・・・・いや、誰だお前はユニティちゃんじゃないな!」
???「グググ・・・ヨク気ヅイタナ・・・」
みたいな演出ができるかもしれませんね!
MirrorReflectionとVRCSDKの方でも動作確認済です。
↓はVRCSDKの鏡
応用技:世界を変える
上の例ではキャラクターのみを差し替えていますが、ステージ・パーティクル・スカイボックスなど、
全てを包括した世界そのものを差し替えることもできます。(スカイボックスは無理だった)
やり方はキャラクターと同じで、レイヤーを切り替えるだけです。
3Dモデル以外のパーティクルも同様です。
↓のgifの場合、「制服ユニティちゃんと町」はRealWorldですが、
「バトルユニティちゃんと廃墟とパーティクル(雨と火)」はMirrorWorldレイヤーになっています。
現実世界は普通の町だが、鏡の中だと廃墟だったり。
鏡の中だけ雨が降っていたり火の海だったりできるわけですね。
あなたの目は本当の世界を映していますか?
注意点
キャラクターの注意点
キャラクターの位置はもちろん、アニメーションも同期させるように注意。
RealWorldとMirrorWorldのキャラクターは同じAnimatorにしておくといいでしょう。
描画処理に注意
鏡全般に言えますが、巨大な鏡の場合は注意が必要です。
キャラクターのみなら大丈夫ですが、巨大な建築物やステージだと処理負荷が高くなることも。
おまけ:Sceneビューでもレイヤー分け
Camera(Gameビュー )と鏡に映るレイヤーを制限することができましたが、
Sceneビューに映るレイヤーも制限することができます。
Unity Editorの左上にあるLayersから、目のマークを押すだけです。
シーン内がごちゃごちゃしてきたら試してみるといいでしょう。
まとめ
・レイヤーを分けることで、カメラと鏡に映るオブジェクトを制限できる
・現実世界のオブジェクトと、鏡面世界のオブジェクトでレイヤーを分ける。
・Cameraと鏡、それぞれ表示するレイヤーを変更する。
使い道としては、「本当の姿を映す」「自分にしか見えない存在を映す」
「キャラクターの感情表現(笑顔だけど本当は悲しんでいるみたいな)」などでしょうか。
ちなみにRealWorldかMirrorWorldどちらかの3Dモデルだけにすれば、
鏡に映らないキャラクターや鏡にしか映らないモンスターを作ることができます。
どちらにせよ表現の幅が広がるのはいいことです。
以上となります。
明日のUnity Advent Calendar 2019は@monryさんによる
「ごっこランドを支える技術 〜AssetBundle 編〜」です。
わかりにくいところなどがありましたら、コメントにお願いします。