テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】Timelineに動的に生成したオブジェクトをバインドする

f:id:tsubaki_t1:20170426221416g:plain

今回はTimelineのデータ情報を流し込む方法についてです。

 

Timelineは使い回せる

Timelineのシーケンスを管理するPlayableAssetsは名前の通りアセットですので、複数のオブジェクトで使いまわす事が可能です。

これを上手く活用すると、特定のイベント…例えば「幅を飛び越える」や「宝箱を開ける」といった部分で、Timelineを活用したアニメーション制御やカメラワーク制御が使用できそうです。

イベントに使う事でAnimatorの構造を簡単にする

 これはTimelineによるモデルに対するアニメーション制御が可能な事を意味しています。なので、例えば「ドアを開ける」「ゲームオーバーになり倒れる」「階段を登る」等の、Animatorで制御すると面倒な(ステートのスパゲティを引き起こしやすい)問題が回避しやすくなります。

ちなみにTimelineのアニメーション流し込みはPlayableAPIを使用しているので、Timelineを使用したくないならPlayableAPIで流し込んでも良いです。

使い回しTimelineを作る時は編集用シーンを用意するが吉

Unity 2017b2で治ってるかもしれませんが、以下のような事があるので、使い回しTimelineを作る時は編集用シーンを作ったほうが良いです。

  1. エディタ操作時のTimelineでシーケンス操作した後に元に戻す機能がスーパー雑
  2. アニメーションはPlayableDirectorではなく親オブジェクトからの相対座標指定で動く

特に2番めの問題があるので、RootMotionが無いキャラクターを移動させるモーションを作る場合は、キャラクターを載せて動かすダミーオブジェクトを用意するのが良さそうです。

Timelineはバインドしたオブジェクトを操作する

Timelineを使いまわす上で重要なのが、オブジェクトのバインドです。

Timelineは基本的にバインドしたオブジェクトを操作します。その為、複数のTimelineが合った場合でも操作する操作する対象を分ける事が出来ます。

例えば上のアニメでは初回のジャンプだけカメラワークの位置が異なります。これは個別にカメラワークの位置を設定出来るために可能な表現です。

f:id:tsubaki_t1:20170426210833j:plain

PlaybleDirectorがオブジェクトへの参照を保持し、Timelineはその情報を使う

Timelineを使う上でのデータのバインドは、多くの場合下のように設定されています。つまり、トラックに露出した項目に設定します。
これをPlayable Directorで見るとBindingsの項目にTimelineで設定したコンポーネントが表示されています。

もしTimelineを複製した際、異なるオブジェクトをバインドしたい場合、PlayableDirectorで参照先を変えてやると、動かす対象が変化します。

f:id:tsubaki_t1:20170426203915j:plain

f:id:tsubaki_t1:20170426204040j:plain

つまりTimelineの参照関係解決の流れは、こんな感じという事です。

  1. Playable Directorにシーン内のオブジェクトへの参照を保持しておく
  2. 実行時、PlayableAssetの情報を元にTrackやAsset、Playable*1を生成
  3. Playable Directorが参照情報をTrackやAssetに参照を流し込む
  4. AssetがPlayableに参照を流し込み、参照情報を使って再生する

 

ちなみにInspectorに表示される項目は設定中にPlayableAssetsの項目ですが、複数のPlayableAssetsの項目が保持出来ます。
これで動的にPlayableAssetsを流し込んだ場合も、バインド機能は動作するという事です。

別シーンのオブジェクトや生成したオブジェクトは動的にバインドする

この参照関係の構築の問題はTimelineが別シーンであったり、動的に生成している場合です。これらは事前に参照関係を設定出来ないので、動的にオブジェクトをバインドする必要があります。

f:id:tsubaki_t1:20170426205659j:plain

PlayableTrackに動的なオブジェクトをバインドする

まずはトラックにバインドします。

PlayableAssetsがバインド可能な項目は、PlayableAssets.outputsから取得出来ます。そこからトラック名が一致するPlayableBindingを取得します。これがPlayableAssetのトラックへの鍵となります。

あとはPlayableDirector.SetGenericBindingで、PlayableDirectorにバインド情報を流し込みます。*2

gist.github.com

なおトラック名とはTimelineのトラック選択時にInspectorに出てくるコレです

f:id:tsubaki_t1:20170426212248j:plain

PlayableAssetに動的なオブジェクトをバインドする

アセットにオブジェクトをバインドします。

こちらは一々個別に設定など出来ないので、Resolverで参照を解決してもらいます。ただExposedReferenceではなく、割とマニュアルな感じです。

 

PlayableAssetのバインドはIExposedPropertyTable経由で保持されている物を使用しています。つまりIExposedPropertyTableにキーとバインドするオブジェクトを与えてやれば良い訳です。
ここでExposedReferenceを使いたい所ですが、ExposedReferenceが設定するキーの値がちょっと分からないので、キーは手前側で勝手に決めてしまった物を使います。

  1. playableDirector.SetReferenceValueでオブジェクトをバインドする。
  2. graph.resolver.GetReferenceValueでバインドしたオブジェクトを取り出す。

gist.github.com

なんでC#のDictionalyでやらないのかという意見があるかもしれませんが、私もそう思います。まぁTimelineの中身がほぼC++っぽいので、こういう形なんでしょうが…

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

*1:PlayableTrackやPlayableAsset

*2:Inspectorは変化しません。

【Unity】リアルタイムな影とベイクした影を混ぜる、Shadow Mask 特集号

f:id:tsubaki_t1:20170418215930j:plain

今回はUnity 5.6で追加されたLightingの新しい機能、特にShadowmaskについてです。

Shadow Maskは動的な影と静的な影を混ぜる手法

まずShadowMaskとは何ぞやという話ですが、要するに動的な影と静的な影を混ぜる新しい手法の一つです。

f:id:tsubaki_t1:20170418221250j:plain

tsubakit1.hateblo.jp

今までMixed系の手法は、ライトマップに焼いた部分は(既に焼いた)ライトの影響を受けず、ダイナミックなオブジェクトのみ影を描画する…という手法でした。
その場合、既に焼いたライトマップに追加でライトが加算描画されるといった事が発生していました。例えば下の場合、赤が動的、青が静的な影です。赤の落とす影が一部濃くなって描画されています。

f:id:tsubaki_t1:20170418223021j:plain

5.6以前でも回避方法は無い訳ではありませんでしたが、5.6のShadow Maskでより綺麗かつシンプルに回避が可能になりました。

下の図ではShadow Maskを使用しています。

f:id:tsubaki_t1:20170418223635j:plain

「影」の計算を事前に行う

ShadowMaskのやっている事は単純で、影を事前に計算しておく事です。
下ではほぼ全てのモデルがリアルタイムな影を持つ場合です。FrameDebuggerで確認すると、Shadows.RenderJobDirで影の計算が行われている事が確認出来ます。

f:id:tsubaki_t1:20170418231014j:plain

ソレに対してShadowMaskで影を生成してみます。今度は赤はDynamic、青はStaticである場合です。
シーンは同じですが、Shadow.RenderJobDirで生成している影のテクスチャには、ダイナミックな赤い球しか表示されなくなりました。
ソレ以外の影は事前にShadowMaskとして計上されています。

f:id:tsubaki_t1:20170418231957j:plain

マスクなので輝度や色を変える事が出来る

Shadow Maskを色々試して気づいた面白い事の一つは、今までのBaked Shadowと異なり輝度や色を変更出来る点です。

f:id:tsubaki_t1:20170418225151j:plain

このミソはShadowMaskはあくまでもマスクであるという点です。

今までは影はベイクするとテクスチャに全て書き込んでいました。そのためテクスチャ自体の色を変えない限り影の色や輝度を変更する事は出来ませんでした。

 

ShadowMaskは単純に「マスク」で、影計算は事前に行いますが光の計算はリアルタイムに行うので、光の色や輝度を変更しても反映する事が出来る訳です。

f:id:tsubaki_t1:20170418225555j:plain

ただし、下にも書きましたが間接光の計算は確定しているので、あまり強力に色を変えたりしない方が良さそうです。少し点滅するくらい。

間接光は事前にテクスチャに焼かれる

影以外の光の計算がリアルタイムで行われるとなったとき気になるのは間接光の扱いですが、事前計算してテクスチャに焼きこまれます。

f:id:tsubaki_t1:20170418232740j:plain

上の内容で「RealtimeGIを設定しとけばGIが更新できる」ようにTwetterで書いてますが、これは自分の勘違いです。
テクスチャにベイクされるので更新出来ません。

光沢が綺麗に出る

Shadow Maskは影の設定だけで光はリアルタイムです。なので光沢もリアルタイムと同じように出ます。

Unity 5.5以前はライトマップにベイクしてしまうと光沢が死ぬ問題がありましたが、ShadowMaskを使えば光沢が表現されます。

下は青がStatic(+Shadow Mask)、赤がリアルタイムです。

f:id:tsubaki_t1:20170419005101j:plain

tsubakit1.hateblo.jp

 Cookieが使える

ShadowMaskは光計算はリアルタイムなので、クッキーが使えます。

f:id:tsubaki_t1:20170419010614j:plain

クッキーで絞り込んでいる場合でも、ShadowMaskは最大範囲で作られるので、少し動かしたり出来るのは若干面白いです。

f:id:tsubaki_t1:20170419011211g:plain

近距離はダイナミックに、遠距離はShadowMaskを使う

個人的に最も気に入っている機能はDistance Shadowmaskの機能です。

この機能では「遠距離の影はShadowMaskを使うが近距離の影はダイナミックに描画する」という機能です。

何が良いかと言えば単純に、影の解像度を減らせます。

f:id:tsubaki_t1:20170418234112j:plain

遠距離に低解像度のShadowMaskを使って、色々と節約

例えば下のシーンでは、17mのリアルタイムシャドウでソレ以外はShadowMaskを使用しています。一見それなりに見えますし、実際近くの影は綺麗に描画出来ています。

f:id:tsubaki_t1:20170418235557j:plain

ShadowMapの解像度を節約

実はここで使用しているShadowMaskは、実はShadowMaskのResolutionは「5」という恐ろしく低い値を設定しています

この解像度でShadowMaskを表示するとボケボケの影が表示される事になりますが、近距離はダイナミックに影を描画する事で、近距離はパッキリと遠距離はボケボケの影が使用できます。

f:id:tsubaki_t1:20170419000059j:plain

これが生むメリットの一つは、Lightmapのサイズです。徹底して低解像度に出来るので、サイズを大きく下げる事が出来ます。

例えば上のシーンに使用しているマップは50*20m級のマップですが、ここで使用しているテクスチャのサイズはたったの341kbに収まります。

これをDistance Shadowを使用せず綺麗な影のライトマップを表現しようとResolution 40(初期値)でやろうと思ったら、11MB近くになり、沢山のメモリと高いロードのコストを払う事になります。

f:id:tsubaki_t1:20170419001248j:plain

またベイクのための解像度が減る事で、ライトマップが少し早く焼けます。

 

なお、Lightmapの解像度を下げるとShadowMaskの解像度だけでなく、間接光の解像度やEmissiveなオブジェクトの解像度、Bakedでテクスチャに焼き込んだ影の品質が下がります。
下の図はResolution2で影をベイクした場合です。staticが近距離では汚く見えます。

f:id:tsubaki_t1:20170419020209j:plain

 リアルタイムな影の負荷を節約 or 高品質化

何より良いのは、手前側のリアルタイムな影の品質も向上する事です。
影に使用するテクスチャは、影の品質で設定したサイズをShadow Distanceで分割していきます。その為、影の描画範囲が狭ければ狭い程、高解像度な影が描画出来ます。

f:id:tsubaki_t1:20170419002354j:plain

もし右のようなフワっとした影が好みなら、ShadowのResolutionを落とせば良いです。それで(Soft Shadowなら)フワっとなりますし、描画負荷も落ちます。

影がShadowMaskになるタイミングは、Cascadeで見ると良いです。

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

2017と5.6でDistance Shadowの設定位置が異なる

まだ確定かは分かりませんが、Unity 2017では設定位置が変化していました。

tsubakit1.hateblo.jp

Shadow Maskの使い方

LightingのLighting ModeをShadowmaskに設定し、ShadowMaskを作りたいライトをMixedに設定するだけです。

f:id:tsubaki_t1:20170419014227j:plain

tsubakit1.hateblo.jp

関連

tsubakit1.hateblo.jp

【Unity】InspectorでCtrl+Clickを押してTextureの簡易ビュー表示

 な、なんだってーーーー

InspectorでCtrl+Clickで簡易プレビュー

MaterialのInspectorビューにて、Ctrl + Clickでプレビューが出来るみたいです。
知らんかった

f:id:tsubaki_t1:20170419020927g:plain

Frame DebuggerやLightmapでも使える

Materialの設定以外でも、Frame DebuggeやLightmapの確認でも使えます。

f:id:tsubaki_t1:20170419021230g:plain

f:id:tsubaki_t1:20170419021409j:plain

関連

No hack, no work • Unity進捗どうですか2

【Unity】シーンの変更を「無かったこと」にする

f:id:tsubaki_t1:20170414030546g:plain

ちょっとしたTipsです。

シーンの変更を「無かったこと」にする

シーンの内容を変更すると、シーン名の右にアスタリスク(*)が表示されます。この状態であれば、シーンの変更を破棄する事が出来ます。

f:id:tsubaki_t1:20170414030659j:plain

  1. Hierarchyのシーンを右クリック
  2. Discard Changesを選択

マルチシーンエディティング等で他のシーンから物を持ってきた時等によく使ってます。

 

勿論、Saveして変更を確定してしまったら戻すことは出来ません。これは「保存してなければ」使えます。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp