テラシュールブログ

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

【Unity】アニメーション制御に色々と良さそうな"Playable API"について云々

今回はUnity 2017.1で正式導入となったPlayable APIについてです。

PlayableAPIはAnimatorのLowLevel API(のようなもの)

まずPlayable APIとは何ぞやという話ですが、大雑把に言えばAnimationを再生する為の物です。

何が便利かと言えば、AnimationControllerを量産する事無くアニメーションを再生動的なアニメーションの追加、そしてアニメーション同士をブレンドする事が期待出来ます。

 

AnimationControllerは、どちらかと言えば全パターンを網羅した物を用意して「すべてを埋めない」に対して、Playable APIは逐次PlayableGraphに追加していくイメージです。

https://cdn-ak.f.st-hatena.com/images/fotolife/t/tsubaki_t1/20160615/20160615234430.gif

ちなみに、この技術はAnimatorだけでなくTimelineにも使用されており、オーディオやスクリプト制御にも応用が効く機能ではあります。
…パーティクルも一緒に制御してくれても良いのよ?

 

なお、Playable APIは余りセーフなAPIでは無いようで、開放忘れ等で簡単にUnityエディターをクラッシュさせます。Threadやstaticと同じように、十分に注意する必要がありそうです。

 アニメーションのブレンド結果をOutputに出力する

Playable APIを説明する場合、大きく分けて3つの要素があります。

Playable GraphPlayableOutput、そしてPlayableです。

 

Playableは、アニメーション再生やオーディオ再生を制御するためのコマンドです。ココでどのアニメーションを再生するのか、どういったブレンドを行うのかを制御します。

Playableの結果を出力する先はPlayable Ouputです。Ouputに出力された結果はバインドしたAnimatorに流し込まれます。

Playable Graphは複数のPlayableやOutputを持つグラフです。

f:id:tsubaki_t1:20170729221944j:plain

要するにoutputに何を流し込むかで、再生するアニメーションが変わります。

AnimatorをPlayable API的に見てみる

Playable APIスクリプトで基本的に作成します。その際、どういった形でグラフが構築されているのかをPlayableGraph Visualizerで確認する事が出来ます。

github.com

これでAnimatorを見てみると、下のようなグラフになります。

f:id:tsubaki_t1:20170729223526j:plain

 AnimationControllerでどのステートで再生するのかを決定、Layerでレイヤー単位のアニメーション加算・上書き合成を制御します。

面白いのが二つのAnimationMixerで、アニメーション切替のタイミングで下に以前再生していたAnimationClip、上に次に再生するAnimationClipを流し込み、アニメーションのブレンドを実現しています。

f:id:tsubaki_t1:20170729223929j:plain

Playable APIを実際に使ってみる

それでは実際にPlayable APIを使用してみます。

なお、日本語マニュアル(Unity 5.4)のサンプルコードは動作しません。最低でもUnity 2017.1のマニュアルが望ましいです

AnimationClipを動的にロードしてアニメーションを再生する

まずはAnimationClipを動的にロードしてアニメーションを再生してみます。

必要な物は5つ。

  • UnityEngine.PlayablesとUnityEngine.AnimationsのNamespace、
  • PlayableGraphの生成と破棄
  • 再生するAnimationを持つAnimationClipPlayable
  • 出力先のPlayableOutput
  • 流し込む先のAnimatorコンポーネント

これで動的に取得したアニメーションをAnimatorで再生する事が可能です。

gist.github.com

f:id:tsubaki_t1:20170729230126g:plain

複数のアニメーションの切替

アニメーションの切替はAnimationMixerPlayableを使います。

まぁOutputへ流し込むAnimationClipを切り替えても良いのですが、Mixerを使用した方がブレンドが出来て便利です。またAnimatorのInitializeも回避出来ます。

gist.github.com

f:id:tsubaki_t1:20170729231923g:plain

正確には切替というより、複数のAnimationClipPlayableのウェイトを変更する感じです。

複数のレイヤー制御

アニメーションを行う場合、表情や上半身・下半身でのレイヤー制御等を行いたくなる場合があります。そういった場合ではレイヤーの加算合成が使えます。

gist.github.com

f:id:tsubaki_t1:20170730004307g:plain

上手く使えばギミックをPlayableAPIで動かすことが可能です。ただし、編集にはAnimatorが必要なので、若干の片手落ち感はあります。

二つのAnimationClipPlayableを使いまわす

AnimationClipPlayableを全登録せず、随時追加・破棄していくパターンです。

gist.github.com

f:id:tsubaki_t1:20170730020401g:plain

基本的にはAnimationControllerで、必要な時だけAnimationClipを足す

ある程度AnimationControllerで制御したいが、(例えば宝箱をあけたり、畑を収穫したり等の)特殊イベント時に任意のアニメーションを足したい場合のアプローチです。

アニメーション終了後にPlayableを破棄します。

gist.github.com

f:id:tsubaki_t1:20170730030538g:plain

PlayableGraphをAnimatorから持ってくる場合は、AnimationControllerはAnimatorから抜いておく必要があります。

 

一応、既に再生中に割り込む方法もありましたが、どちらかと言えばAnimationControllerPlayableを使用したほうが安定する印象です。

tsubakit1.hateblo.jp

注意点

  • エディターで、ゲーム再生中にフォーカスが外れた状態で放置すると、再開時にアニメーション再生がゆっくりになる(ビルドした物はフォーカスが外れても大丈夫)
  •  PlayableGraphを開放忘れると落ちる事がある(ので、AwakeとOnDestroyで生成・開放を管理)
  • 開放漏れ等は「2回目の再生」で落ちる

【Unity】AssetBundleをマネージコードのStreamから取得する

f:id:tsubaki_t1:20170724220902j:plain

Unity 2017.2よりAssetBundle.LoadFromStreamとAssetBundle.LoadFromStreamAsyncが追加されました。

これで暗号化したAssetBundleをStreamから読み込んだり、独自圧縮したAssetBundleを読み込んだり…?うーん、出来るのかな

サンプルコード

下のようなコードでAssetBundleが取得出来ます。

gist.github.com

まぁコードに関してはスクリプトリファレンスの方が多分ちゃんとしてます。

Unity - Scripting API: AssetBundle.LoadFromStream

Unity - Scripting API: AssetBundle.LoadFromStreamAsync

色々な制限が

おお便利そう!と思いましたが、色々と制限が…

  • AssetBundleのデータはStreamの位置が0である必要がある
  • AssetBundleの値を読むときはSeekの位置が0になる
  • 他のプロセスが位置を変更しない前提
  • stream.CanReadはTrueを返す
  • stream.CanSeekはTrueを返す
  • Streamは別スレッドからアクセス可能であること

ただ、Streamを自作すれば結構色々と出来ます。ファイルを暗号化してみた結果がこちら

tsubakit1.hateblo.jp

そして未来へ…

それは兎も角、AssetBundleの今後の予定されてる破壊的変更の前には、この程度のことは無いに等しい…

詳しくは、見れば分かるさ…見ればな…

www.slideshare.net

www.youtube.com

 

ちなみに、複数のCacheフォルダを持ったり、指定Cacheを削除したりは既に出来ます。

docs.unity3d.com

関連

docs.google.com

https://forum.unity3d.com/threads/preview-of-2017-2-features.481949/

【Unity】SpriteMaskでSpriteにマスクを掛ける演出が色々と面白い

Unity 2017.1より追加されたSpriteMaskの機能が意外と面白いので、少しメモします。

SpriteMask

SpriteMaskはSpriteを利用してSpriteRendererにマスクをかける機能です。
画像をSpriteの形にくり抜いたり、逆にSpriteをくり抜いたり出来ます。

f:id:tsubaki_t1:20170721003252j:plain

機能的には現状存在するSpriteに対してマスクを掛ける…程度の機能ではありますが、意外とコレは利用の幅が広そうです。

 

操作方法

使い方に関しては正直マニュアルが詳しいです。

docs.unity3d.com

壁に穴を開ける

壁に穴を空けてみます。これはUnityTipsに上がっていたものを自分なりに解釈したものです。

f:id:tsubaki_t1:20170721003328g:plain

まず最初の状態がコレです。

SpriteMask等は何も設定していないので、キャラクターの前面に地面が表示されています。

f:id:tsubaki_t1:20170721003954j:plain

次にSpriteMaskをキャラクターの子GameObjectに追加し、キャラクターの前面の地面のSpriteRendererにはMaskIntaraction Visible Outside Masksを設定します。

SpriteMaskをキャラクターの子GameObjectに設定するのは、そのほうが柔軟にマスクする範囲を決められるからです。

f:id:tsubaki_t1:20170721004310j:plain

f:id:tsubaki_t1:20170721004301j:plain

 

後はマスクで抜いた先の背景も設定しておきます。
背景はキャラクターよりOrderInLayerが奥のSpriteを用意しておき、そのMask Interactionはnoneに設定しているだけです。

これでマスクでくり抜いたら背景がいきなり空…みたいな事は回避出来ます。

f:id:tsubaki_t1:20170721004558j:plain

同様に、SpriteMaskを使用してシルエットを表示させる事も可能といえば可能です。ただしシルエット色を変えられる以外のメリットが無いので、ソレをするならStencilでやった方が良いんじゃないかなという気はします。

Spriteの消滅演出をSpriteMaskで

マスクはアルファのカットアウト(アルファブレンドではない!)で、SpriteMaskのα値を変えればスプライトの消滅演出を追加したり出来ます。

例えば下の場合、簡単なルール画像を用意すれば実現出来ます。

f:id:tsubaki_t1:20170721010817g:plain

For You さんのページよりルール画像を入手して、ルール画像の透明度ルールはFrom Grayscaleに変更。

後はSpriteMaskのAlpha Cutoutを設定すれば、うまい感じに切り抜いてくれます。

ただ、ルール画像によっては最後まで綺麗に切り抜いてくれない事があるので、そのあたりが出たらルール画像を調整する必要があるかもしれません。

f:id:tsubaki_t1:20170721011116j:plain

実はパーティクルのマスクも出来る

もう一つ面白いのが、実はSpriteだけではなくParticleSystemにもマスクが使えるという点です。例えば下のように、パーティクルの生成をマスクの形でカットしています。

f:id:tsubaki_t1:20170721010048g:plain

f:id:tsubaki_t1:20170721011935j:plain

ただひとつ問題になるのがSpriteMaskが複数合った場合です。
例えば下の図では、右下の赤いパーティクルと左上の黄色いパーティクルが、お互いのマスク範囲内に混ざってしまっていることが確認出来ます。

f:id:tsubaki_t1:20170721011612j:plain

これはSortingGroupで解決出来るみたいです。てっきりSprite用かと思ってましたが、意外と使えるもんです。

親にSortingGroup、子にSpriteMaskとParticleを配置すると、上手い感じにパーティクルをマスクしてくれます。

f:id:tsubaki_t1:20170721011845g:plain

f:id:tsubaki_t1:20170721083548j:plain

tsubakit1.hateblo.jp

関連

tsubakit1.hateblo.jp

halcyonsystemblog.blog.fc2.com

tsubakit1.hateblo.jp

【Unity】ダッシュで移動した際の土煙っぽい表現

f:id:tsubaki_t1:20170719210027g:plain

今回はキャラクターが移動した時の土煙について、よく考え方を忘れるのでメモしておきます。

移動時の土煙

自分の好きな演出の一つに「移動時の土煙」という物があります。
これは漫画やアニメ等で良くあるダッシュで移動した事を表す記号で、キャラクターの移動速度や軌跡を上手く表してくれます。

f:id:tsubaki_t1:20170719210633g:plain

煙の表現ですが、以前は基本的にアルファブレンドで煙のテクスチャをばら撒いていましたが、最近はCubeをばら撒くのがマイブームです。

ので、Cubeをばら撒くアプローチの方法について書いておきます。

f:id:tsubaki_t1:20170719211225j:plain

土煙の表現

土煙の表現を行う際に一番手っ取り早いアプローチは、ParticleSystemを使う事でしょう。とりあえずこの4つのモジュールを使います。

f:id:tsubaki_t1:20170719210915j:plain

作ったパーティクルは、動くキャラの足元から少し上辺りにおいておくと良いです。

向きと大きさはランダム、座標はワールド

まず基本的な部分ですが、Simulation SpaceがWorldになってる事です。これで向きを変えた時もLocal座標ではなくWorld座標でParticleを生成してくれます。便利便利

f:id:tsubaki_t1:20170719211402j:plain

もう一つ、StartSizeとStart Rotationを操作して開始時の向きを切り替えておきます。

この項目は初期値と違って範囲指定出来るようにしてあります。これは、項目右の▼から設定できます。

回転やサイズは固定でもある程度見栄えは付きますが、やはりココはランダムであって欲しいという、コダワリポイントです。

f:id:tsubaki_t1:20170719212420j:plain

移動時の生成量

移動時の生成量を設定します。Rate over Distanceで移動に応じてパーティクルを出してくれるようになるので、コレを使ってキャラクターが移動したときに足元にパーティクルを出してもらいます。

f:id:tsubaki_t1:20170719211710j:plain

足元辺りに生成する

Shapeで出現位置を少しランダムにします。演出的には無くてもそれ程変わらないといえば変わらないのですが、合ったほうが多少は良い感じの見栄えになる印象です。

f:id:tsubaki_t1:20170719212540j:plain

範囲は足の範囲くらいが良いです。場合によってはEdgeやCircleでも良いかもしれません。

最初は小さく、一気に膨らんで、最後は縮んでく

Size Over Lifetimeで、最初は小さいが一気に膨らみ、段々小さくなるようにします。このさじ加減で演出が大体決まります。

f:id:tsubaki_t1:20170719212721j:plain

パーティクルとして生成するのはモデル

こんかいの演出ではCubeを生成しています。理由はそのほうがカッコイイからです。
一応、Meshのパーティクルはそこそこ重い部類に当たるので、注意して使ったほうが良いです。

モデルなのでStandardShaderも気にせず使います。頂点カラーが使えませんが、今は気にしません。

f:id:tsubaki_t1:20170719213002j:plain

後は影を落とし、かつ影を受ける設定です。

これで完成

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp