テラシュールブログ

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

【Unity】Cubeを跳ねさせる

f:id:tsubaki_t1:20170731002426g:plain

今回は小ネタというか、やってみたと言うか…豆腐を跳ねさせるという内容です。

Cubeだって跳ねる

ゲームの仮素材ランキングがあるとしたら、多分ブッチギリで人気No1はCubeでしょう。かのスプラトゥーンですらプロトタイプはCubeだったと聞きます。

つまりCubeには無限の可能性があります。ならば、Cubeは跳ねる事が可能なハズです。

とりあえず、跳ぶ!

とりあえずアニメーションでCubeを跳ねさせてみます。

初期値点から一定時間で最高高度へ、そして一定時間で初期値点へ。リニアな移動です。

f:id:tsubaki_t1:20170731002835g:plain

f:id:tsubaki_t1:20170731002922j:plain

か、硬い…!

跳ねてると言うより、上から吊るして持ち上げてると言った方がシックリくるレベルの動きです。

カーブを付ける

跳ねる動きを考えてみます。

基本的にジャンプする瞬間は最高速度で上へ移動し、段々と重力に引かれて減速、最終的に初期加速より重力が勝って落下を開始して、最後に着地…という流れです。

f:id:tsubaki_t1:20170731003448j:plain

f:id:tsubaki_t1:20170731004256g:plain

f:id:tsubaki_t1:20170731004112j:plain

大分ジャンプしてる感が出てきました。

通常のキャラクターならこれでも十分なのですが、Cubeでジャンプだとまだ十分ではありません。なぜならCubeにはモーションが無いからです。

豆腐はフルフルする

Cubeにモーションを設定してみます。

しかしCubeには関節はありません。ならばどうするか…Scaleを使います。

Cubeのような物がジャンプするには、どんなモーションが必要か。

  • 平べったくなり力を溜める
  • 反動で上に跳ねる(縦に伸びる)
  • 縦に伸びた反動でフルフルする
  • 落下開始
  • 地面に着地した衝撃でぺたんこになる

f:id:tsubaki_t1:20170731004828j:plain

f:id:tsubaki_t1:20170731004842j:plain

これで跳ねます。
単純なScaleですが、タイミングを調整することで何というか見ていて気持ちのよい感じの動きになったんじゃないかなと思います。

f:id:tsubaki_t1:20170731005119g:plain

頂点単位でモーフしたい?うるせぇ豆腐ぶつけんぞ

 

という事で、異世界転生したらCubeだって勇者を目指せる話でした。

…言語チート欲しい。英語に対応してるやつ

関連

www.youtube.com

【Unity】Playable APIで幾つかの小技

昨日のPlayable APIで書ききれなかった事を少し追記します。

tsubakit1.hateblo.jp

複数のAnimatorに単一のPlayableを流し込む

PlayableGraphにOutputは実は複数作ることが出来ます。コレを利用すると、複数のオブジェクトを完全に同期した状態でアニメーションさせる事が出来ます。

f:id:tsubaki_t1:20170730124159j:plain

またOutputでアニメーションを流し込んだ場合でもアバターはAnimator毎に制御されているので、Humanoidならボーン構造の異なる物でもアニメーションが可能です。

アニメーションのコストがかかるのはスキニングの部分なので大した意味はありませんが、何かに使えるかもしれません。

f:id:tsubaki_t1:20170730123706g:plain

AnimationClipPlayableが共通化されているので、一つのAnimationClipPlayableを操作すれば一気に複数のアニメーションが制御出来るのは中々に面白いです。

逆を言えば、少しずつタイミングをズラしたようなアニメーションは出来ない点には注意が必要です。

f:id:tsubaki_t1:20170730124714g:plain

gist.github.com

アニメーションの出力先を切り替える

outputは出力先を切り替えることも出来ます。

例えばキャラクターが選択された際のモーション等があった時、キャラクター一人ひとりにPlayableGraphを作るのはナンセンスなので、PlayableGraphだけ作って出力先を切り替えてしまう訳です。

f:id:tsubaki_t1:20170730130343j:plain

なお、Output出力先を切り替えてもアニメーションは最初から再生される訳ではありません。最初から再生したい場合は、PlayableのTimeを0に戻す等の操作が必要そうです。

f:id:tsubaki_t1:20170730130658g:plain

gist.github.com

Additiveの再生

ギミックを動かす等を行う時、Additiveで動かせると一々親オブジェクトを用意しなくても良いので何かと便利です。

Playable APIの場合、AnimationLayerMixerPlayableにAdditiveのオプションがあるのでソレを使用します。

f:id:tsubaki_t1:20170730134049g:plain

gist.github.com

tsubakit1.hateblo.jp

【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/