テラシュールブログ

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

【Unity】「アニメーションが再生されない」「止まる」時の対処法

今回は「アニメーションをセットアップしたのに再生されない」や「アニメーションが止まる」といった場合の対処法についてです。知っていれば「当然そうなる」(そういう設定をしている)という動作なのですが、知らないと面倒かもしれないので一覧としてメモします。

なおアニメーションをDCCツール(MayaやBlender)から出力する事それ自体に問題がある場合は含みません。

Animation ClipのLoopが無効になっている

アニメーションが途中で止まる場合、AnimationClipのLoopが外れているかもしれません。

AnimationClipは多くの場合FBX(等のファイル)から取得しますが、このアニメーションはAnimationタブの中から切り出して取得します。この時、Loopの設定が外れていると、アニメーションの完了時にアニメーション再生がポーズします。

この設定の特徴は、AnimatorControllerで見たときにステートの進行が最大値で停止しているので分かりやすいです。

f:id:tsubaki_t1:20190111202502j:plain
アニメーションのループ

f:id:tsubaki_t1:20190111202611j:plain
ステートの再生が最大で停止する

一つ厄介なのが、アニメーションの停止ではなくポーズであるという事です。アニメーションは停止しますがAnimatorによるパラメーターの更新は停止しておらず、Transformの情報は毎フレーム更新され続けています。

そのため、もしUI(特にLayoutGroup)に対して使用すると、毎フレームUIが更新され続けてすごい負荷になるといった事もあります。Playable APIを使用したアニメーションの場合は再生後に正しい意味で停止するので、動作後に停止するような動きを作る場合にはSimpleAnimatorやTween系を検討するのが良さそうです。

リグがアニメーションを取得したFBXとモデルのFBXで一致していない

FBXでよくあるもう一つの設定が、リグの不一致です。

このリグは基本的にアニメーションを再生するFBXと、アニメーションを取得するFBXで一致している必要があります。HumanoidはHumanoidのアニメーションを、LegacyはLegacyのアニメーションを使用できます。

f:id:tsubaki_t1:20190111203901j:plain
リグの設定一覧

またGenericやLegacyの場合はリターゲット機能は無いので、ボーン構造も含めて一致する必要があります。

アバターが一致しない

Humanoidでデータを取得する場合に重要なのがアバターです。アバターは人形のボーン構造と実際のモデルのボーン構造を一致させる効果があります。このボーン構造が一致していないと、アニメーションは再生しません。

例えば下の場合、キャラクターはMCUnitychanのボーン構造をしていますが、実際に適応しているのはEthanAvatar…異なるアバターが適応されているので動かないといった具合です。

f:id:tsubaki_t1:20190111205158j:plain
モデル本来のアバター

f:id:tsubaki_t1:20190111205101j:plain
モデルのアバターではないアバターを設定

どのアバターか分からない場合、オブジェクト内のSkinnedMeshRendererを探し、Meshを生成しているFBXをたどれば見つけられます。

f:id:tsubaki_t1:20190111205632g:plain
アバターを探せ

子のAnimatorを最適化している

少し特殊なケースですが、Animatorを階層構造にしたとき子のAnimatorが最適化していると動きません。

子の最適化を解除すれば、動作するようになります。最適化を描けたい場合は親のAnimatorで行います。

ステートマシンにClipが登録されていない

ステートマシンにクリップが登録されていない場合、当然アニメーションは再生しません。

登録したつもりでも登録してなかったり(後で差し替えるつもりだった)、GUIDの変更により剥がれる等。

f:id:tsubaki_t1:20190304125827j:plain
クリップが「無し」

AnyStateからのステート切り替えが常に成立している

AnyStateからステート切り替えが常に達成している場合、同じアニメーションが何度も再生されます。AnyStateはステートマシンを無視してステートを切り替えるので、ステート遷移条件が達成している限り現在のステート(自分自身)から自分自身のステートへ切り替えが発生してしまいます。

f:id:tsubaki_t1:20190304125037j:plain
AnyStateは他のステートからアニメーションを切り替える

また遷移間隔が0の場合は見た目殆ど停止している状態になります。

f:id:tsubaki_t1:20190304124946j:plain
遷移間隔が0 = アニメーション遷移終了後に即座に他のステートに移れる

対処法としては、AnyStateからの遷移から「自身に遷移」のチェックボックスを外す事です。これで少なくとも「毎フレーム自分のステートを再生し直す」事は回避出来ます。ただ、根本からの解決を考える場合は、何度もAnyStateからジャンプするステートマシンを何とかするべきでしょう。

個人的にはAnyStateには遷移条件にTriggerを必ず含めるべきと思ってます。

f:id:tsubaki_t1:20190304125328j:plain

なおAnimator.Playは自分自身に遷移しても停止しません。3番目の引数であるNormalizeTimeまで指定すると、その時間で止まりますが。

Timescaleが0

Timescaleが0(時間の流れるスピードが0 = 時間停止 = ザ・ワールド)だと、アニメーションは再生しません。

正確にはコレは設定次第で、Animatorの設定を「スケールされていない時間」にすることで回避出来ます。

f:id:tsubaki_t1:20190304123920j:plain

これにより「止まった時の中でも動ける」ようになりますが、同時に「加速した時間の恩恵」も受けられなくなる点に注意です。

f:id:tsubaki_t1:20190304124008g:plain
時間が流れる速度を無視して、常に一定速度で動く

【Unity】Assembly definition fileのDefine Constrainsで、Scripting Define Symbolsで定義したシンボル毎に動作を切り替える

Assembly definition fileに少し便利な機能が追加されていたので、メモ

本記事はUnity 2018.3がベースです。

Assembly definition file

簡単に言えばコンパイルプロジェクトを分割することでコンパイルの高速化等を行うというものです。この機能を理解しないで適当に使うと逆にコンパイル時間が伸びるかもしれませんが、ちゃんと使うと結構有益なイメージです。

また、なんとなくIL2CPP時のインクリメンタルビルドにも影響がある気がしていますが、実際どうなのかは未確認です。

tsubakit1.hateblo.jp

Assembly definition fileとプラットフォームによる動作の切り替え

Assembly definition fileはプラットフォーム毎に含めるかどうかを定義することが出来ます。例えばIOSのみ、Androidのみコード群を含めると言った具合に。この機能を上手く使うと、エディター上の動作と実機の動作用のプロジェクトは完全に分割することが出来ます。

インターフェースをちゃんと定義する必要はあると思いますが、コード群が非常にスッキリするんじゃないでしょうか。勿論インターフェースの用意を忘れずに。

f:id:tsubaki_t1:20190303231729j:plain
プラットフォームごとにAssembly Definition Fileを分割

Define Constrains(制約を定義)

さて、今まではこういった「Assembly Definition Fileによる動作の切り替え」はプラットフォーム単位でしか出来ませんでしたが、「制約を定義(Define Constrains)」という機能が追加され、手前側でも追加でコントロールすることが可能になりました。

f:id:tsubaki_t1:20190303232243j:plain

この機能は、単純にScripting Define Symbolsにシンボルが記述されていなければ、Assembly Definition Fileのプロジェクトは含まれない というものです。

例えばプラットフォームEditorにて、シンボル毎に動作を切り替えたいとします。まぁデバッグ用とか、ロード先の切り替えとか云々。で、制約を定義でそれぞれ「MY_DEBUG1」と「MY_DEBUG2」というシンボルを要求する感じにします。

f:id:tsubaki_t1:20190303233848j:plain

あとはPlayerSettingsScripting Define Symbolsを差し替えてやるだけで、動作が切り替わります。

f:id:tsubaki_t1:20190303233815j:plain

なお含まれるのは「何もシンボルを指定していない」もしくは「シンボルが一致するもの」です。(なのでMY_DEBUG1とMY_DEBUG2に分けた)

感想

最初はAssembly definition file毎にシンボルを指定できる機能だと思ったのは秘密。mcs.rspをプロジェクト毎に置くといった事も駄目だし、うーん

関連

tsubakit1.hateblo.jp

【Unity】シーン内のGameObjectやAsset、メニューアイテムを検索できる「Unity Quick Search」

f:id:tsubaki_t1:20190301004750j:plain

プロジェクト内のオブジェクトやアセット、メニュー操作等を検索出来る「Unity Quick Search」がPackage Managerに追加されました。

Unityプロジェクト内の色々な物が検索できる

Unity Quick Searchは、OSXの「Spotlight」やWindowsの左下にあるなにか(検索ボックスというらしい)に似た機能です。この機能では、ショートカットキーからテキストボックスを起動し、色々なものが検索出来ます。

例えば

  • アセット(名前ベース)
  • シーン内のオブジェクト
  • メニューアイテム
  • ソースコード(名前のみ、Package含む)
  • 設定
  • アセットストア

等々、割と色々と探せます。

なおUnity 2019.1で確認しており、それ以前のバージョンで使えるかは見ていないです。

使い方

使い方は簡単、日本語キーボードだと「Alt + ^」(英語だとAlt + ' ?)を押して、メニューを開きます。

あとは検索したいキーワードを入力して、検索するだけです。SceneやAssetのオブジェクトは、ドラッグ&ドロップで配置等も出来ます(トップのGifアニメのように)

f:id:tsubaki_t1:20190301001615g:plain

f:id:tsubaki_t1:20190301003155g:plain

詳しい使い方は、マニュアルがGifアニメ大量で非常に分かりやすいので、そちらを

docs.unity3d.com

拡張してみた

この機能は拡張できるそうです。
せっかくなので、拡張してみます。

やってみたのは、指定のタグを使用しているオブジェクト一覧を取得というものです。タグはオブジェクトに依存した挙動を作る際には使うことがあるのですが、何故か未だにタグを検索する機能がありません。なので今回それを作ってみました。

検索で「tag:○○」と入力すれば、○○と一致するタグを見つけてきます。

コードのポイントは、SearchActionsProvider属性を持つメソッドと、SearchItemProvider属性を持つメソッドを定義しておけばOKです。

検索対象はfetchItemsに突っ込む内容で判断しています。

それ以外は基本コピペです。AssetとSceneの二通りの検索例があるので、その辺りでコピペすれば何とかなります(多分)

gist.github.com

補足

メニューの検索は、英語が前提です。日本語のメニューは検索にヒットしません。

f:id:tsubaki_t1:20190301004015j:plain

試した所、複数の要素で絞り込みは出来ませんでした。やり方が悪い?

感想

OSXのSpotlightをよく使う勢としては、割とありがたいです。

(ところでProject Viewの検索はもうちょっと賢くなっても良いと思う。具体的には新しく追加されたタイプに対応するとか)

【Unity】UnityでAlembicを使ってみる

Package ManagerにAlembicが追加されたので、試してみました。

Alembicとは?

Alembic for Unityの説明が分かりやすいので引用します。

Alembic は主に映像業界で使われているデータフォーマットで、巨大な頂点キャッシュデータを格納するのに用いられます。 映像業界では、スキニングやダイナミクスなどのシミュレーション結果を全フレームベイクして頂点キャッシュに変換し、それを Alembic に格納してレンダラやコンポジットのソフトウェアに受け渡す、というような使い方がなされます。
Alembic 本家: http://www.alembic.io/

要するにモデルをボーンで変形させるのではなく、頂点まるごとストリーム再生する的な感じでしょうか。おかげで、下のような水のシミュレーションも比較的低負荷で再生することが出来るみたいです。

f:id:tsubaki_t1:20190228135324g:plain
Alembic for Unityのページより引用

Unity PackageにAlembic Importerが追加

先日、Alembic ImporterがPackage Managerに追加されました。しかもPreviewをすっ飛ばして最初からリリースされています。

f:id:tsubaki_t1:20190227222731j:plain
PackageManagerから確認出来る

それもそのはずで、本質的にはGithubで公開されているAlembic for Unityを使用しているっぽいです。正確には若干異なるみたいですが、まぁ確かに実績のあるシステムなので、最初から問題が無いと判断したのでしょう。

ということでUnity 2018.3で導入してみると導入出来ません。

f:id:tsubaki_t1:20190227223146j:plain
Unity 2018.3でAlembicを導入してみた結果

どうやらPackage ManagerのAlembicはTimelineのパッケージを要求するみたいです。

つまりPackageのAlembicが使えるのは実質的には2019.1からで、まだTimelineがPackage化していないUnity 2018.3では使えません。その場合は普通にGithubのAlembic for Unityを使うのが良さそうです。

github.com

使い方

使い方に関して言えば、正直Githubのリポジトリにある説明が詳しいです。

日本語のマニュアルがあります。一部若干違う部分もあるかもしれませんが、多分フィーリングで何とかなります。

実際に試してみる

実際に試してみます。

とは言え、Alembic(.abc)ファイルを見つける事が出来なかったので、とりあえずAlembicをExportしてImportしてみます。

まず最初に シーンの動きをAlembicとして出力 してみます。

適当なオブジェクトに Exportコンポーネント(Package managerならば Alembic Exportコンポーネント)を追加します。あとはBegin Recordingボタンを押してゲームを再生→終了です。ゲームを終了するとレコードも停止します。

https://user-images.githubusercontent.com/1644563/53494896-17555900-3ae2-11e9-82df-0227bf332dc3.gif

これで .abc ファイルがOutputフォルダに出力されます。

f:id:tsubaki_t1:20190227225125j:plain
プロジェクトフォルダ/Outputにファイルが出力された

コレをUnityに再インポートして使ってみます。

Alembic 導入後は普通にドラッグ&ドロップで .abc が使えます。ただしインポート直後はマテリアルが剥がれているので、設定する必要があります。マテリアルの設定は普通のUnity的なマテリアル設定手順です。

マテリアル差し替える時に気づいたのですが、出力前はSkinnedMeshRendererだった物もすべてMeshRendererに差し替わっています。ボーンベースのスキニングではなく、頂点を動かしているという事でしょう。

f:id:tsubaki_t1:20190227225622j:plain
導入直後はマテリアルが剥がれている

マテリアル設定後はAlembic Stream PlayerのTimeを動かしたり、TimelineのAlembic Trackを使用することでストリーム再生が出来るみたいです。

f:id:tsubaki_t1:20190227230142g:plain

感想

自分の出来る範囲内では、以前紹介したRecorderと似たような立ち位置ですが、Alembicはストリームで再生出来るという点で良いように思います。代わりに .abcファイルはStreamingAssets等のUnityが観測しないIOに入れる事になりますが、逆にAssetBundleを使わず使えるので、利点の一つといえるのかもしれません。

正直、VRは幾つかのインタラクティブ要素を除いたらAlembic等をストリームで流し込む方が理に適ってるんじゃないかなと個人的には思わなくも(モバイルだとIO周りで詰まりそうですが)

関連

Recorderを使用するアプローチ

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

blogs.unity3d.com

www.youtube.com