UnityのAnimatorでUIアニメーションを作る詳細

この前のプロジェクトでは、古いバージョンのLegacy Animationを使用するか、またはまだ試用段階にあるPlayable Graph +Animation Jobを使用するかの方法で、アニメーションを作りました。

 

最近のプロジェクトでは、Animatorを使用してアニメーション、特にUIアニメーションを作成しました。ここに詳細の一部を記録します。

 

##状態遷移
UIアニメーションは通常、すべての状態遷移をAnimator Controllerに配置する必要はありません。なぜかというと、これらの遷移はコードで直接操作する必要がある場合は多いからです。たとえば、UIフォームには、開き状態と閉じ状態（それぞれOpen、Closeと表記する）がありますが、一般的には、それらを自動的に切り替える必要はなく、遷移（Transition）もありません。したがって、いくつかの方法が考えられます。

1.意味のある状態（OpenやCloseなど）は孤立したノードとして、遷移しません。

2.意味のある状態が完了すると、「何もしない」状態に遷移します。

3.意味のある状態が完了すると、Exit状態に遷移します。

 

Animator Controllerの状態では、StateMachineBehaviorクラスから継承されたスクリプトをハングアップでき（MonoBehaviourと同じ、スクリプト名とクラス名は同じである必要があります）、基本クラスStateMachineBehaviorにはOverrideできる多くのコールバックがあります。

 

ある状態が終了すると、OnStateExitコールバックを実装して、「この状態のアニメーション再生が終了しました」とプログラムの他の部分に通知できます。ただし、上記の最初のアプローチを使用する場合、再生状態は終了しないため（別の状態が再生されない限り）、OnStateExitをコールバックしてもトリガーされません。

 

後者の2つの方法は、UIの開きや閉じのような要求に対してそれほど違いはありません。私たちが取ったのは、「現在のステートマシンを直接終了する」という最後のアプローチです。Animatorの動作は、Exit状態を終了し、すぐにEntry状態から再入することです。不要な操作を回避するために、OnStateExitコールバックでAnimatorオブジェクトのenabledプロパティをfalseに設定しました。

 

次の図は、私が使用したアニメーションの状態遷移図です。新しく追加された状態の1つは、Entryの後に使用する必要があります。これは、図の「Do nothing」ノードです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/0aef3169-2eb4-1bab-e26f-3224f68c9d02.png)
---
##アクティブ化時最初のフレーム
UIを作成する際に、便宜上、UIのPrefabは開いた後の状態にする必要があります。

 

たとえば、そのScaleは1である必要があります。Canvas Groupがある場合、Alpha値は1である必要があります。羊皮紙の巻物を作成する場合は、開き状態である必要があります。しかし、UIを開こうとしているときは、最初のフレームから、ScaleとAlphaが0に近く、羊皮紙の巻物が閉じているように見えます。次に、この情報をアニメーションクリップのキーフレームに書き込むことに加えて、Animatorコンポーネントを保持しているゲームオブジェクトは、アクティブ化されるとアニメーションの再生を開始することにも注意してください。最初のフレームでちらつきの問題がある場合は、ここで提供される解決策を参照できます。

---

##デフォルト
アニメーションの終了後にAnimatorコンポーネントを非アクティブに設定する方法（つまり、上記の3番目の方法）を使用しない場合は、デフォルト値の問題に注意を払う必要があります。

 

上記のように、UI Prefabは開いた後の状態である必要があり、Animatorで取得できるすべてのレベルのゲームオブジェクトとそのコンポーネントの属性値がこの状態の値になります。ただし、以下のような問題に注意してください。

![微信截图_20211029163354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/91b216d8-3b27-ac52-1cc0-8c01a41fe213.png)
 

初めてOpenアニメーションを再生するのは正しいですが、再生が完了すると、開き終了状態にとどまるように見えます。初めてCloseを再生しても問題ありません。通常のUI実装方法をシミュレートするために、Closeが完了した後、ゲームオブジェクト全体がSetActive（false）にして、それで2回目の開きの後、問題が発生します。 Openアニメーションが再生された後は、開き終了状態ではなく、閉じ終了状態にとどまっています。これはどうしてですか？

 

各アニメーションの状態を選択すると、そのInspectorから[Write Defaults]プロパティが選択されていることがわかります（下の図を参照）。つまり、現在のアニメーションが特定の属性を操作しない場合、この属性の値はデフォルト値（Animatorがアクティブ化される前に表示される値）のままになります。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/2f7e78c0-35f5-9a24-35ef-61656906e679.png)
一方（下の図を参照）、状態遷移矢印を選択すると、「Has Exit Time」オプションが選択されていることがわかります。次のデータは、ソース状態の正規化時間（Normalized time）が0.75に達すると、この状態遷移が次の状態遷移を開始することを示しています。遷移時間は0.25秒の固定期間です。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/533ddda8-855c-db0e-3ea7-f9026c55dde5.png)

したがって、OpenまたはClose状態が75％に達すると、次の状態への遷移が開始されます。ターゲット状態がExitであるため、Animatorは再びEntryに入り、さらに「Do nothing」状態に遷移します。また、この状態は空（アニメーションクリップなし）であり、デフォルトでWrite Defaultsが選択されているため、ゲームオブジェクトのプロパティはデフォルト値に復元されます。

 

SetActive（false）の場合、ゲームオブジェクトのプロパティは以前のデフォルト値に復元する時間がなかったため、閉じ終了状態にとどまっていると思います。次回にAnimatorコンポーネントを実行するときは、Open Exit Entry Do nothingを通して、Do nothingはデフォルト値とします。

 

上記の3番目のアプローチを使用すると、この問題が避けられます。それ以外、「Do nothing」の「Write Defaults」を逆選にすることができます。それなら、この状態に入るときに、前の状態が再生終了のプロパティ値が維持されます。

---
##結び
単純なUIアニメーション、特にUIフォームの開き・閉じアニメーションにとって、Animatorが基盤実装として場合：

1.Entryノードの後にDo nothingノードを新規作成します。これは、何もしない状態を示します。
2.開き・閉じアニメーションはそれぞれ一つの状態と見なすことができ、出口はExitノードを指します。
3.ちらつきを避けるために、最初のフレームの再生タイミングに注意してください。
4.アニメーションが再生終了のコールバックで、Animator.enabledをfalseに設定すると、プログラムが引き継ぎます。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

今なら、UWA GOTローカルツールが**15日間に無償試用**できます！！
よければ、ぜひ！

UWA公式サイト：https://jp.uwa4d.com
UWA GOT OnlineレポートDemo：https://jp.uwa4d.com/u/got/demo.html
UWA公式ブログ：https://blog.jp.uwa4d.com