テラシュールブログ

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

【Unity】Timelineのクリップが動かすオブジェクトを動的に更新する方法

f:id:tsubaki_t1:20170922224305g:plain

今回は、昨日紹介したControlTrackのControl Playable Asset Clipに、任意のオブジェクトを動的にバインドする方法についてです。

Timelineの中身を動的に更新したい

Timelineを映像系ではなくゲームで使用する場合、実行時に動的に操作する対象を差し替えたくなるといったケースがあるかもしれません。

 

例えばITimeControlで操作するGameObjectを差し替えたり、Cinemachineで参照するVirtual Cameraを切り替えたり、動かすキャラクターを差し替えたり。

 

動かすキャラクターといったTrackで制御する物に関しては、下の記事の方法で解決出来ますが、クリップに関しては少し面倒です。

tsubakit1.hateblo.jp

クリップの値は参照する物と実体を持つものがある

f:id:tsubaki_t1:20170922214702j:plain

クリップの値ですが、少し複雑です。

 

通常、クリップの値は、Timelineのアセット(PlayableAsset)が保持しています。この値はアセットとして保持されていて、基本的に固定値のような扱いです。

ただし、シーン内のオブジェクトを参照するような内容…例えばGameObjectやAnimatorへの参照等は、PlayableDIrectorからPlayableAssetが吸い出して解決するような方法で解決しています。

 

この意味は、値を保持するタイプの物は動的に書き換えると他のすべてのTimelineが影響してしまいますが、参照のみの場合はPlayableDirectorの値をチョチョっと書き換えてやれば、捜査対象をハック出来るという意味です。

Control Playable Asset Clipの参照先を書き換える

せっかくなので、昨日紹介したControl Playable Asset Clipの参照先を切り替えてみます。

サンプルコードはこちら。

gist.github.com

解説

まず15行目、名前からトラックを取得します。
トラック名は、Inspectorで書き換えられます。

f:id:tsubaki_t1:20170922220008j:plain

 

次に16行目、トラック一覧から上書きしたいクリップを取得します。
こちらも同様にInspectorから書き換え可能です。

f:id:tsubaki_t1:20170922220019j:plain

 

そして18行目で、オブジェクトが参照を解決するためのキーを取得し、19行目で値を登録します。

ここで注意すべきは、Control Playable Asset ClipはITimeControlではなくGameObjectを受け付けるという点です。なので、コンポーネントからGameObjectを取得して渡します。

実際に動かす例

コードを用意したら、PlayableDirectorのあるオブジェクトにRebindコンポーネントを追加します。

その後、ボタン等でRebindのPlayメソッドをITimeControlを持ったオブジェクトを引数にして呼び出してやれば、回転します。

f:id:tsubaki_t1:20170922220733j:plain

f:id:tsubaki_t1:20170922222141g:plain

もっと手っ取り早い方法

ちなみに、対象がControl Playable Asset Clipの場合はもっと手っ取り早い解決方法があります。

実はControl Playable Asset Clipは子オブジェクトも動かすオプションがあります。このオプションがonの場合、SourceGameObjectの子のITimeControlも一緒に操作してくれます。

f:id:tsubaki_t1:20170922222939j:plain

要するに、事前に用意したオブジェクトの子として、指定のオブジェクトを動かしてやるというアプローチです。
下のような動作をソースコード側でやります。

f:id:tsubaki_t1:20170922223624g:plain

手順

まず、適当な親オブジェクトを用意します。名前はBindedObjectとか適当にそんな感じで。

次に、ControlPlayableAssetにBindedObjectを登録します。

f:id:tsubaki_t1:20170922223201j:plain

後は、動的にオブジェクトの子として動かしたいオブジェクトを登録します。先程のコードを少し改造したものです。

gist.github.com

これでも、動的にオブジェクトが更新されます。

既に動作してるTimelineは更新出来ない点に注意

一点だけ注意があります。

それはこの方法では既に動作しているTimelineの参照を上書きできないという点です。

 

Timelineの参照解決はTimeline再生開始時に行われるのが通例らしく、参照関係を解決した後に流し込む内容を更新しても意味がないという事みたいです。

ちなみにPreviewのON/OFFでも参照関係の構築が走るみたいなので、上手く動かないときはPreviewをON/OFFすると解決するかもしれません。わんぽいんと

 

次はTImelineの階層化とかパーティクルとか

関連

tsubakit1.hateblo.jp

https://forum.unity.com/threads/timeline-available-in-unity-2017-1.455265/page-6#post-3217752

tsubakit1.hateblo.jp

【Unity】ITimeControlで、Timelineから"コンポーネント"を操作する

今回はTimelineのクリップからMonobehaviourを継承したコンポーネントを手軽に操作する方法について紹介します。

f:id:tsubaki_t1:20170921230441g:plain

Timelineで手軽に動かしたい

Timelineでキャラクターを動かす時、大抵の場合はAnimationで物を作っていく訳ですが、それでは色々と面倒なケースが多々あります。例えばUVスクロールする背景や、単純にキャラクターを回転させたいようなケースです。

f:id:tsubaki_t1:20170921231607g:plain

こういった項目はPlayableを自分で作れば簡単に回避出来るには出来るのですが、その為だけにPlayableを作るのは割と面倒です。またTimelineの有無に関わらず動かしたいといったケースも考えられます。

 

そういった時にITimeControlは便利です。

ITimeControlインターフェースはTimelineから呼ばれる

インターフェースの一つにItimeControlという物があります。これはControl Playableで設定していた場合、ヘッドがクリップを通過中に呼び出される…という物です。

docs.unity3d.com

コンポーネントにインターフェースを付けるだけで良いので、Playableを云々するよりもかなり簡単に実装できるのは中々に良いです。

但し、インターフェースから受けられるのは「実時間」で、クリップ全体の長さは受けられない点には注意が必要です。そっちはPlayableを頑張る感じで。

実際に回転させる

実際にITimeControlを使ってみます。
このサンプルでは上のGifにあるように、対象を回転させます。

コードの準備

まず、iTImeControlを継承したコンポーネントを用意します。

内容は単純に、Speedの速度かつAxisの軸で回転させる…という物です。

出来たらコンポーネントを適当なGameObjectに追加します。

 

gist.github.com

 

ここで個人的に思うポイントは、毎フレーム加算するのではなく、時間で再現出来るようにする事です。加算する場合は巻き戻しても進んでも常に時間が進んでしまいますので。

ただ、振動とか、そういった物は別に可逆でなくとも良いかも。

Timelineにコンポーネントの付いたオブジェクトを登録する

次にオブジェクトをTimelineに登録します。

この時使用するのはControl Trackです。

f:id:tsubaki_t1:20170921232719j:plain

次にAdd Control Playable Asset Clipを追加して、作成したClipのSource Objectに先程ITimeControlを追加したオブジェクトを登録します。

f:id:tsubaki_t1:20170921232832j:plain

f:id:tsubaki_t1:20170921233057j:plain

これでControl Playable Asset Clip上を通る際、ITimeControlのコールバックが呼び出されるようになり、ゲームを再生しなくともコンポーネント側の動きを再現したり出来るようになります。

補足

ちなみに、Animationや他の項目と異なり、プレビューを解除しても元の位置に戻らないので、イベントで開始時の位置を覚えておいて終了時に戻すのオススメ。Tweenとかする場合。

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

www.slideshare.net

【Unity】TextMeshProのアウトラインは、uGUIのと比べてとても良い

f:id:tsubaki_t1:20170920045940j:plain

前回に続きTextMeshPro。今回はアウトラインについてです。

TextMeshProのアウトライン

f:id:tsubaki_t1:20170920054157j:plain

まず本題です。

TextMeshProは、シェーダー側でアウトラインを実現しています。元々SDFでフォントを実現する仕組みなので、その辺りは割と簡単に出来ているのかなと。

アウトラインの設定方法

アウトラインの設定は、マテリアルのOutlineのThicknessから行います。

この項目を増やすと、文字にアウトラインが付きます。

f:id:tsubaki_t1:20170920054618j:plain

ただ実際に行えば分かる通り、このアウトラインは内側に進みます。太いフォントでもThicknessの値が大きい場合、文字のシルエットが変化してしまうかもしれません。

f:id:tsubaki_t1:20170920054847j:plain

内側滲む対策は、文字を広げる事で回避

この内側に滲む問題の手っ取り早い対策は、文字を広げてしまうことです。

FaceのDilateの値をOutlineのThicknessと同じくらいの値を設定してやると、内側への滲みと文字の広がりが丁度よい感じに相殺されます。

f:id:tsubaki_t1:20170920055053j:plain

f:id:tsubaki_t1:20170920055222j:plain

 

アウトラインの色々なエフェクトを試してみる

TextMeshProのアウトラインは色々と出来ます。

例えば、Faceの色を透明にして中抜きアウトラインを表現したり、SoftnessやGrowを活用してボケた感じのアウトラインを作ったり、ぶっといアウトラインを用意したり云々。

f:id:tsubaki_t1:20170920060118j:plain

ただ、ぶっといアウトラインを表現する場合、アウトラインも含めて1文字である事に注意が必要です。アウトラインが隣の文字を侵食します。

 Spacingで文字の間を詰めると、こんな表現になるかもしれません。

f:id:tsubaki_t1:20170920060451j:plain

 

ポリゴン数も増えず、オーバードローも無い。レイアウトにも優しい

TextMeshProで良い点の一つは、uGUIの文字ずらしアウトライン系と異なり、ポリゴンが増えず、オーバードローがない点です。

実際にUI Profilerで確認しても、ポリゴンは通常のフォントと同じ1文字6点のみ。またアウトラインの有無にかかわらず同程度の表現であることが確認出来ます。

f:id:tsubaki_t1:20170920055742j:plain

f:id:tsubaki_t1:20170920055755j:plain

特にポリゴンが少ないので、レイアウト変更したときのコストは割安です。

 

uGUIのアウトライン手法と問題について

一方uGUIのアウトラインはどうでしょう。

uGUIのアウトライン表現は、上下左右にズラシた文字を利用したアウトラインです。この手法では、上下左右に少しずつズラした文字+中央の文字でアウトラインを表現しています。

http://tsubakit1.sakura.ne.jp/images/201406210055390f9.gif

細い文字はアウトラインを太くしにくい問題

まず起こるのが、細い文字はアウトラインを太くしにくい…という事です。

文字をズラして表示する関係上、細い文字…例えばLightと名前が付くようなフォントでアウトラインを表現しようとすると、十分な太さに移動する前に、はみ出てしまいます。

f:id:tsubaki_t1:20170920051007j:plain

ただまぁ、これは実は強引に解決することが出来なくはないです。

uGUIのアウトラインは「UIを利用してアウトラインを作る」ので、小さめのアウトラインを連打することである程度の太さのアウトラインを実現出来ます。

f:id:tsubaki_t1:20170920051509j:plain

色を変えると分かりやすいかもしれません。

f:id:tsubaki_t1:20170920051727j:plain

しかし、このアプローチは場合によっては地獄を呼びます。

文字を表現するために沢山の描画が発生する問題

アウトラインでもう一つ問題になるのがオーバードローです。

単純にアウトラインの文字を一つ書くには、エッジ用に上下左右で4、中央で1の5枚描画する必要が出てきます。

この辺りUI Profilerで確認すると、とても光っているのが確認できます。

白ければ白いほど、ヤバイです。

f:id:tsubaki_t1:20170920052138j:plain

まぁオーバードロー自体は実はそれ程問題にならないかもしれません。オーバードローは描画面積が広ければ問題になりますが、所詮文字です。多分範囲は限定的でしょう。

 

どちらかと言えば、気になるのはもう一つ。ポリゴン数です。ワイヤー表示すると、中々にエグい表示が確認出来ます。

f:id:tsubaki_t1:20170920052457j:plain

特にUIがちょくちょく更新される場合、かつ文字数が多いような場合は、レイアウトコストやら云々が結構なコストになるかもしれません。

具体的にはコレくらい。

f:id:tsubaki_t1:20170920052927j:plain

ソレはソレとして

まぁ実際問題、文字が背景に溶け込まないようにする事が目的の場合、アウトラインは薄いの一つで問題ないかもしれないので、そこまで問題にはならないかもしれません。

またダイナミックフォントが使えるのは、かなり強力なuGUIのメリットです。使いやすい物をケースバイケースで使い分けるのが良いかなと。

関連

tsubakit1.hateblo.jp

indie-du.com

tsubakit1.hateblo.jp

www.youtube.com

【Unity】TextMeshProのMaterial Presetを増やす方法

f:id:tsubaki_t1:20170919223923g:plain

久しぶりの更新は、TextMeshProのMaterial Presetを増やす方法について。

TextMeshProは文字を表現するのに便利な表現

f:id:tsubaki_t1:20170919231014j:plain

https://www.assetstore.unity3d.com/jp/#!/content/84126

 

TextMeshProは、フォントを表現する際に便利な機能です。

(uGUIと比較して)高度なレイアウトシステム、(uGUIと比較して)多機能な表現、(uGUIと比較して)良いパフォーマンス、(uGUIと比較して)手間が多いのが特徴です。

www.slideshare.net

 

最も特徴的なのはズームしてもフォントが綺麗…という所です。

uGUIはゲーム画面(シーンビューの解像度ではない)の画面解像度からフォントの解像度を生成します。そのままなら余り問題は無いのですが、フォントをスケールすると、フォントがボケて見えてしまうかもしれません。TextMeshProはこの辺りを工夫して描画しているため、ズームしても滲みません(但し、事前準備が必要)。

この機能から、自由にカメラの移動が可能なVRや、文字演出等の表現に向いてます

f:id:tsubaki_t1:20170919232644g:plain

また単純にアウトラインがuGUIより綺麗です。

 

 

Material Presetでエフェクトのあるマテリアルを選択

TextMesh Proでフォントにアウトラインやノーマル、サーフェースを設定する場合、マテリアルの設定を変更します。パラメータをシェーダーに流し込み、表現自体はシェーダー(GPU側)で行う事で、CPU側の負荷を下げています。

お陰で、文字の表面をスクロールしても、CPU負荷は0です。

f:id:tsubaki_t1:20170919225138g:plain

 

このマテリアルの差し替えは、Material Presetを使用します

ただし、FontAssetを生成した直後は設定可能なマテリアルは一種類しか無い為、複数のエフェクトを設定する事が出来ません。

複数のテキストを用意した際、Material Presetの値は共有されているため、一つのテキストのエフェクトを変更したつもりでも他のテキストもエフェクトがかかってしまいます

f:id:tsubaki_t1:20170919225353j:plain

ここでFontAssetを増やすのはナンセンスなので、マテリアルを増やしてMaterialPresetで複数のエフェクトを持てるように設定します。

 

Material PresetはCreate Preset Materialで増やす

肝心のマテリアルを増やす方法ですが、Create Preset Materialのメニューを使用します。

FontAssetのマテリアルを選択中、Inspectorでマテリアルのコンテキストメニューを表示でCreate Preset Materialが選択出来ます。この方法で増やしたマテリアルはTextMeshProのMaterial Preset一覧に表示されます。

f:id:tsubaki_t1:20170919230409j:plain

f:id:tsubaki_t1:20170919230550j:plain

f:id:tsubaki_t1:20170919230628g:plain

また、この方法で生成したマテリアルはDeplicate(複製)で量産しても、Material Preset一覧に表示されます。

f:id:tsubaki_t1:20170919230811j:plain

これで色々なエフェクトが使い放題

関連

www.slideshare.net

qiita.com

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

雑記

そして7日後、SNSは再開された で思うことがあったので、月初めに思い切ってスマホからTwitterを消した所、Twitter依存がかなり減った。

ただ、同時にブログ更新意欲がガッツリ減った。どうやら自分のブログ更新モチベーションはTwitterの反応とかその辺りから来てるっぽい。むむむ