MRが楽しい

MRやVRについて学習したことを書き残す

UnityEventを使ってInspectorビューから実行処理を指定する その1(UnityEventの使い方)

本日は Unity の技術調査枠です。
UnityEvent を使って Inspector ビューから実行処理を指定する方法をまとめます。
以下の記事で作成した長押しタッププロジェクトを流用します。
bluebirdofoz.hatenablog.com
f:id:bluebirdofoz:20190207005002j:plain

UnityEvent

UnityEvent は関数そのものを引数として設定するコールバックの機能を提供します。
特色として Inspector ビュー上に設定UIを表示することができます。
docs.unity3d.com

UnityEventを用いた長押しタップスクリプト

長押しタップスクリプトを UnityEvent を用いたものに修正します。
UnityEvent のメンバ変数を追加し、長押しタップ時に Invoke() を実行する形にしました。
・LongTapEvent.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// IInputHandler を利用するため InputModule を追加
using HoloToolkit.Unity.InputModule;

// UnityEvent を利用するため Events を追加
using UnityEngine.Events;

public class LongTapEvent : MonoBehaviour,
IInputHandler // タップダウン、タップアップ検出
{
    /// <summary>
    /// グローバルリスナーの有無
    /// </summary>
    [Tooltip("グローバルリスナーの有無")]
    public bool IsGlobalListener = false;

    /// <summary>
    /// 長押しタップ実行処理
    /// </summary>
    [SerializeField, Tooltip("長押しタップ実行処理")]
    private UnityEvent LongTapUnityEvent;

    /// <summary>
    /// 長押しタップ検出時間(秒)
    /// </summary>
    [SerializeField, Tooltip("長押しタップ検出時間(秒)")]
    private float LongTapTime = 3.0f;

    /// <summary>
    /// 長押しタップ計測開始時刻
    /// </summary>
    private float p_LongTapStart;

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start()
    {
        if (IsGlobalListener)
        {
            // 全てのジェスチャーイベントをキャッチする
            // 本設定を有効にしてColliderオブジェクトにアタッチした場合
            // オブジェクトへのタップとグローバルのタップが
            // 別々に検出される(2回処理が走る)ので注意
            InputManager.Instance.AddGlobalListener(gameObject);
        }
    }

    /// <summary>
    /// タップダウン検出
    /// </summary>
    /// <param name="eventData"></param>
    public void OnInputDown(InputEventData eventData)
    {
        Debug.Log("TapDown!");

        // 現在の時刻を検出時刻として記録
        p_LongTapStart = Time.time;
    }

    /// <summary>
    /// タップアップ検出
    /// </summary>
    /// <param name="eventData"></param>
    public void OnInputUp(InputEventData eventData)
    {
        Debug.Log("TapUp!:" + LongTapTime);

        // 現在時刻の取得
        float nowTime = Time.time;

        // 長押しタップ検出時間より長くタップされていれば長押しと判定
        float tapTime = nowTime - p_LongTapStart;
        if (tapTime > LongTapTime)
        {
            // 長押しタップ処理
            Debug.Log("LongTap");
            // UnityEventを実行
            LongTapUnityEvent.Invoke();
        }
    }
}

LongTapEvent.cs をアタッチしたオブジェクトの Inspector ビューを確認します。
すると、以下のように UnityEvent を設定するパネルが表示されています。
f:id:bluebirdofoz:20190207004939j:plain

実行処理の作成

UnityEvent に設定する実行処理を持ったクラスを作成します。
このときの注意点として、指定する関数は public 関数である必要があります。
以下のようなオブジェクトを2倍の大きさにする関数を持ったクラスを作成しました。
・ChangeScale.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeScale : MonoBehaviour {
    public void ToDouble()
    {
        // オブジェクトを2倍の大きさに変更
        transform.localScale = transform.localScale * 2.0f;
    }
}

作成したスクリプトSphere オブジェクトにアタッチします。
f:id:bluebirdofoz:20190207005017j:plain

作成した関数を実行処理として指定します。
LongTapEvent.cs の UnityEvent にある「+」ボタンをクリックします。
f:id:bluebirdofoz:20190207005027j:plain

作成された項目に、実行したいスクリプトを保持するオブジェクトを指定します。
今回の場合、Sphere オブジェクトを指定します。
f:id:bluebirdofoz:20190207005036j:plain

すると関数のプルダウンに、そのオブジェクトが保持するクラスと利用可能な関数の一覧が表示されます。
先ほど作成した ChangeScale クラスの ToDouble 関数を指定します。
f:id:bluebirdofoz:20190207005049j:plain

これで設定完了です。
「再生」ボタンをクリックして動作を確認してみます。
f:id:bluebirdofoz:20190207005101j:plain

長押しタップを行ったとき、拡大処理が実行されれば成功です。
f:id:bluebirdofoz:20190207005112j:plain
イベントの検出クラスと処理の実行クラスを分けることができるため、機能追加や処理の切り替え、スクリプトの流用が容易になります。

次は UnityEvent での引数の指定についてです。
bluebirdofoz.hatenablog.com