しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

MRDesignLab の Button で MMD のモーションを制御したい

※ これは 2017/10/21 MixedRealityToolkit-Unity for Unity 2017.2.0f3 時点の情報です

最新版では動作が異なる可能性がありますのでご注意ください

BoundingBox の次は Button を配置してみたい

MRDesiginLab に含まれる CompoundButton でサーバルちゃんのモーションの再生と停止を制御してみます

まずはモーション制御の仕組みを作るため、Surval オブジェクトにアタッチしていた Animation Controller をダブルクリックし Animator ビューを開きます

Unity の Animator ビューでは状態遷移図のような設定画面でアニメーションの遷移を設定できるのでこちらを利用します

Animation Controller を開くとアニメーションが再生される nekomimi_lat_vmd のステートが Entry ステートから直接遷移していました

ここに待機状態のステートを追加して間にはさみ、条件によって nekomimi_lat_vmd のステートを行き来するように変更します

適当な箇所を右クリックして [Create State]-[Empty] のコンテキストメニューを選びます

新しいステートが追加されるので、名前を Idle に変更

できた Idle ステートを選択し、コンテキストメニューから Set as Layer Default State を選び、初期ステートを nekomimi_lat_vmd から Idle に変更します

さらに Idle のコンテキストメニューから Make Transition を選び、表示される矢印を nekomimi_lat_vmd につなぎます

同様に nekomimi_lat_vmd からも Make Transition で Idle に矢印をつなぎ双方向に遷移を設定してます

ここでモーション再生/停止の切り替えるための条件フラグを追加するため、Animator ビューの左上のほうにある Parameters タブを選択、+ ボタンから新しく Bool の変数を追加し名前を「Playing」としておきます

次に Idle → nekomimi_lat_vmd の遷移矢印を選択し、Conditions のエリアの右下 + ボタンで条件を追加、先ほど追加した Playing を選択し、値を true の場合に指定します

同様に nekomimi_lat_vmd → Idle の遷移矢印を選択し、Conditions のエリアの右下 + ボタンで条件を追加、先ほど追加した Playing を選択し、値を false の場合に指定します

モーション再生途中でも切り替わるように Has Exit Time のチェックは外しておきます

モーション制御の準備はできたので、今度は CompoundButton を追加します

Project ビューの MRDesignLab/HUX/Prefab/Buttons/CircleButton の Prefab を選択し、Hierarchy ビュー上にドラッグドロップで配置します

名前は PlayButton に変更し、サーバルちゃんの前あたりに表示座標を調整

さらにこの PlayButton を選択し、Inspector ビュー上の Icon として「!」マークを選択します

この PlayButton を Duplicate のコンテキストメニューで複製し、名前を StopButton に変更

こちらも Icon を × のマークに設定しました

また、PlayButton、StopButton の入力を制御するため、Hierarchy ビューのコンテキストメニューから Create Empty を選んで空の GameObject を作成し、名前を Reciever とします

この Reciever の Inspector ビューから Add Component ボタンで New Script を選び、SurvalInteractionReceiver という名前で C#スクリプトファイルを作成しアタッチします

この SurvalInteractionReceiver .cs の記述は下記の通り

using HUX.Interaction;
using HUX.Receivers;
using UnityEngine;

public class SurvalInteractionReceiver : InteractionReceiver
{
    /// <summary>
    /// アニメーションコントローラー
    /// </summary>
    [SerializeField]
    private Animator animator = null;

    /// <summary>
    /// Play ボタン
    /// </summary>
    public GameObject PlayButton { get { return this.Interactibles[0]; } }

    /// <summary>
    /// Stop ボタン
    /// </summary>
    public GameObject StopButton { get { return this.Interactibles[1]; } }

    /// <summary>
    /// 初期処理
    /// </summary>
    public void Awake()
    {
        this.PlayButton.SetActive(true);
        this.StopButton.SetActive(false);
    }

    /// <summary>
    /// タップイベントハンドラ
    /// </summary>
    /// <param name="obj">イベント発行者</param>
    /// <param name="eventArgs">イベント引数</param>
    protected override void OnTapped(GameObject obj, InteractionManager.InteractionEventArgs eventArgs)
    {
        switch (obj.name)
        {
            case "PlayButton":
                this.PlayButton.SetActive(false);
                this.StopButton.SetActive(true);
                this.animator.SetBool("Playing", true);
                break;

            case "StopButton":
                this.animator.SetBool("Playing", false);
                this.StopButton.SetActive(false);
                this.PlayButton.SetActive(true);
                break;
        }
    }
}

MRDesignLab の InteractionReceiver を継承し、OnTaped イベントハンドラだけ override して Animator の Playing フラグによって PlayButton と StopButton によるモーション制御、各ボタンの表示切替を行うようにしました

最後にこの SurvalInteractionReceiver に対し、Surval オブジェクトにアタッチされた Animator、ドラッグドロップで設定し、さらに Interactibles の Size を 2 に増やし、Element 0 に PlayButton、Element 1 に StopButton をドラッグドロップでアタッチします

これで UnityEditor 上でとりあえず動かしてみました

! ボタンをタップするとモーション再生が開始、× ボタンで停止するようになりました