

アニメーションしながら開閉するダイアログを作りたいけど、どうすれば良いか分からないの…


Unity標準のアニメーションとスクリプトを組み合わせれば出来るわ。具体的な手順付きで分かりやすく解説していくね。
Unityでアニメーションしながら開閉するダイアログの実装方法の紹介です。
本記事を実践すると、次のようなダイアログが実装できます。
次の要件を満たすダイアログを実現していくことを本記事の目標とします。
- 開く、閉じるメソッドでダイアログを開閉できる
- アニメーション中は操作できない
- 不正な操作にも対応する
なお、本記事の手順を実践するにあたり、Unityエディタ操作とC#スクリプトの基礎知識が必要になりますので、予めご了承ください。
- Unity2021.2.0f1
キャンバスの配置
何もないシーンにuGUIのキャンバスを配置するところから手順を進めていきます。
Hierarchyビュー左上の+ボタンからUI > Canvasの順に選択し、キャンバスを配置します。
上の動画では、Canvas ScalerコンポーネントのUI Scale ModeをScale With Screen Sizeにし、Reference Resolutionを以下のように設定しました。

ダイアログの配置
アニメーションさせる対象となるダイアログのUIを配置していきます。
背景パネルの配置
背景となる長方形パネルを配置します。
HierarchyビューのCanvasを右クリックし、UI > Panelの順に選択してパネルをCanvas配下に追加します。
上下左右に余白を持たせるため、例ではRect Transformを次のように設定しました。

閉じるボタンの配置
ダイアログを閉じるためのボタンを配置します。
HierarchyビューのPanelを右クリックし、UI > Buttonの順に選択してボタンを追加します。
例では、ボタンを下中央に配置するため、Rect TransformのアンカーとPos Yを調整しています。

また、ボタンのオブジェクト名を分かりやすい名前に変えておくと良いでしょう。ボタンのテキストもCloseに修正します。 [1]
開閉アニメーションの作成
ダイアログを開閉させるアニメーションを作成していきます。
アニメーターコントローラーの作成
まず、開閉アニメーションの状態遷移を定義するためのアニメーターコントローラーを作成します。
Projectビューの右クリックから、Create > Animator Controllerの順に選択し、適当な名前を入力してEnterキーで決定します。
例では、Assets/Animations/フォルダ配下に、Dialogという名前のアニメーターコントローラーを作成することとしました。

状態の作成
先に作成したアニメーターコントローラーを開き、開閉アニメーションの状態遷移を定義していきます。
アニメーターコントローラーファイルをダブルクリックし、Animatorビューを開きます。
Animatorビュー内で右クリックし、Create State > Emptyの順に選択します。
すると、New Stateという状態が作成されます。

このオレンジ色の状態が初期状態です。今回は初期状態はダイアログが開いているとします。
状態をクリックし、分かりやすい名前に変更しておきます。ここではShownとします。
再びAnimatorビューの何もないところで右クリックし、Create State > Emptyの順に選択します。先と同じ要領で状態名を隠れている(Hidden)に変更します。
これでダイアログが開いている、閉じているの2つの状態が作成されました。

フラグの定義
ダイアログが開いているか閉じているかを表すためのフラグを定義します。これは、スクリプトからフラグが変更されたときに、状態を遷移できるようにするためです。
AnimatorビューのParametersタブ > +ボタン > Boolの順にクリックします。パラメータ名を入力してEnterキーで決定します。
初期状態は開いているとするため、チェックをつけておきます。

状態遷移の定義
状態遷移を定義するためのトランジションを作成します。
Shown状態を右クリックし、Make Transitionを選択し、Hidden状態でクリックします。
更に、トランジションの線をクリックして状態遷移を設定します。
以下の内容で設定します。

Conditions > +ボタンをクリックし、フラグを追加します。値はfalseになったときにHidden状態に遷移させるため、falseに設定します。

同じ要領で、HiddenからShown状態への遷移も定義します。こちらのトランジションのConditionsのフラグはtrueにします。

アニメーターコントローラーのアタッチ
先の手順で配置したダイアログパネルにアニメーターコントローラーをドラッグ&ドロップでアタッチします。
開くアニメーションの作成
Projectビューで右クリックし、Create > Animationを選択し、アニメーションクリップを作成します。名前はOpenとしました。

AnimatorビューのShown状態を選択し、Motionに先に作成したOpenのアニメーションクリップをドラッグ&ドロップします。
OpenアニメーションクリップをダブルクリックしてAnimationウィンドウを開き、更にHierarchyビューのダイアログパネルを選択します。
すると、AnimationウィンドウのAdd Propertyボタンがアクティブになります。

アクティブにならない場合は、もう一度Hierarchyビューのダイアログパネルを選択してください。
Add Propertyボタンをクリックし、Rect Transform > Scaleの順に選択し、スケールアニメーションのトラックを追加します。
そして、以下動画のようにアニメーションを設定してください。
パネルのスケールが0から1に変化するようにして、開くアニメーションを実現しています。
Animationウィンドウの再生ボタンをクリックし、ダイアログの開くアニメーションがループ再生されれば成功です。
閉じるアニメーションの作成
開くアニメーションと同じ要領で、閉じるアニメーションも作成していきます。
操作方法は概ね開くアニメーションのときと一緒のため、設定動画で示すのみにとどめます。
開くアニメーションとは逆に、スケールが1から0に変化します。
ダイアログ開閉スクリプトの作成・適用
ダイアログをボタン等で開閉できるようにするためのスクリプトを作成します。名前はAnimatedDialogとします。
内容は以下の通りにします。
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// ダイアログのアニメーション
/// </summary>
public class AnimatedDialog : MonoBehaviour
{
// アニメーター
[SerializeField] private Animator _animator;
// アニメーターコントローラーのレイヤー(通常は0)
[SerializeField] private int _layer;
// IsOpenフラグ(アニメーターコントローラー内で定義したフラグ)
private static readonly int ParamIsOpen = Animator.StringToHash("IsOpen");
// ダイアログは開いているかどうか
public bool IsOpen => gameObject.activeSelf;
// アニメーション中かどうか
public bool IsTransition { get; private set; }
// ダイアログを開く
public void Open()
{
// 不正操作防止
if (IsOpen || IsTransition) return;
// パネル自体をアクティブにする
gameObject.SetActive(true);
// IsOpenフラグをセット
_animator.SetBool(ParamIsOpen, true);
// アニメーション待機
StartCoroutine(WaitAnimation("Shown"));
}
// ダイアログを閉じる
public void Close()
{
// 不正操作防止
if (!IsOpen || IsTransition) return;
// IsOpenフラグをクリア
_animator.SetBool(ParamIsOpen, false);
// アニメーション待機し、終わったらパネル自体を非アクティブにする
StartCoroutine(WaitAnimation("Hidden", () => gameObject.SetActive(false)));
}
// 開閉アニメーションの待機コルーチン
private IEnumerator WaitAnimation(string stateName, UnityAction onCompleted = null)
{
IsTransition = true;
yield return new WaitUntil(() =>
{
// ステートが変化し、アニメーションが終了するまでループ
var state = _animator.GetCurrentAnimatorStateInfo(_layer);
return state.IsName(stateName) && state.normalizedTime >= 1;
});
IsTransition = false;
onCompleted?.Invoke();
}
}
ダイアログを開くOpenメソッドと、ダイアログを閉じるCloseメソッドを持つMonoBehaviour継承クラスです。これらのメソッドを後述するボタンクリック操作で呼び出します。
そして、次のようにダイアログパネルにスクリプトをドラッグ&ドロップでアタッチして設定します。

ボタンでダイアログを閉じれるようにする
ここまで適用できたら、閉じるボタンがクリックされたときに、ダイアログを閉じれるようにしていきます。
閉じるボタンオブジェクトのButton > On Click()を以下動画のように設定します。
実行結果
開く操作の設定
ここまで手順で、ダイアログを閉じる操作まではできるようになりました。
初期状態はダイアログが非表示で、ボタンを押したら開くようにしていきます。
ボタンクリック時のメソッド呼び出しは、閉じるボタンの時と同じ要領です。
また、ダイアログパネルは非アクティブにしておきます。開くボタンを押す前は非表示にしておくためです。

実行結果
ここまでの手順を成功させると、ボタンでダイアログをアニメーション付きで開閉できるようになります。
ボタンを連打してもおかしな動作をせずに動くようになっています。
さいごに
非常に手順が長くなりましたが、ダイアログをアニメーション付きで開閉する手順を解説しました。
実は、ダイアログを開いたり閉じたりしたあとのイベント通知処理などは敢えて入れていません。この辺の実装は開発するコンテンツによって異なってくる可能性があるためです。
当サイトで制作するゲームは、UniTaskを用いたasync/awaitの非同期処理で押されたボタンなどの結果の受け渡し処理を実装しています。
今回は外部アセットやライブラリを使わない方法で開閉処理を実装しましたが、適宜開発するコンテンツに合わせてふさわしい形にアレンジして使うと良いでしょう。