MagicLeap2 コントローラ入力の情報まとめ

MagicLeap2 コントローラ入力サンプル - TechnicalProtein

↑の記事で触ったController Input Event についての追加情報、ここで紹介されている以外のボタン入力とかはこちらの記事に書いてます

SDK 0.53.3 現在の情報

UnityのInputSystemを利用してMagicLeap2のコントローラの入力をトリガーする方法のおさらい

using UnityEngine;
using UnityEngine.InputSystem;


namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            // 各入力のイベントハンドラを登録.
            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.started += HandleOnBumperStarted;
            _controllerActions.Bumper.performed += HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled += HandleOnBumperCanceled;
        }
    

        private void OnDestroy()
        {
            // 登録していたハンドラを削除.
            _controllerActions.Bumper.started -= HandleOnBumperStarted;
            _controllerActions.Bumper.performed -= HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled -= HandleOnBumperCanceled;

            // 入力の購読を終了.
            _mlInputs.Dispose();
        }

       
        private void HandleOnBumperStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Bumper is started.");
        }
        

        private void HandleOnBumperPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is performed.");
        }


        private void HandleOnBumperCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is canceled.");
        }
        
    }
}

手順としては

  1. MagicLeapInputs 、フィールド名 _mlInputs

  2. _mlInputs.Enable() で起動

  3. MagicLeapInputs.ControllerActions、フィールド名 controllerActions のインスタンスを作成時に mlInputs を渡し、関連付けを行う

  4. InputAction.CallbackContext を引数にとるイベントハンドラを作成

  5. 取得したい入力のイベントに登録 ( 今回は Bumper ボタン )

  6. 購読の用がなくなったら 登録したイベントを削除し、_mlInputs.Dispose() で入力の購読を終了する

購読するイベントタイプ

イベントタイプ 解説
InputAction.started 入力の開始時に呼び出される
InputAction.performed 入力されている間呼び出される
InputAction.canceled 入力が終了時に呼び出される

まとめ

簡単にだが MagicLeap SDKAPI を利用したコントローラ入力をまとめた 一応公式APIの入力をそのまま使う以外にMRTKを利用した入力も今度書こうと思う

MagicLeap2 コントローラ入力サンプル

やること

MagicLeap2 のコントローラの入力サンプルコードの紹介 動作確認は実機がないためMagicLeap HubのApplicationSimulatorにて確認しています

前提条件

↓の手順でMagicLeap2の開発環境を整えている必要があります

developer-docs.magicleap.cloud

サンプルスクリプト

マニフェストの設定

まずは Eidt > ProjectSettings > MagicLeap > ManifestSettings から CONTROLLER_POSE のチェックを入れる 執筆時点( 2022/9/19 SDK ver 0.53.3 )ではその項目はなかったが取れた

マニフェスト設定

スクリプト

UnityEngine.InputSystemを利用しているため、AssemblyDefinitionでアセンブリ空間を切ってる人は以下の参照の紐づけを忘れずに

  • MagicLeap.SDK
  • Unity.InputSystem

流れとしては MagicLeapInputs と MagicLeapInputs.ControllerActions のインスタンスを作成し、MagicLeapInputs.ControllerActions のインスタンスに MagicLeapInputs を紐づけ。 その後 MagicLeapInputs を起動し、購読したい入力のイベントを登録する。

namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.performed += HandleOnBumper;

        }
    

        private void OnDestroy()
        {
            // 入力の購読を終了.
            _mlInputs.Dispose();
            _controllerActions.Bumper.performed -= HandleOnBumper;            
        }


        private void Update()
        {
            // Update で直接確認することも可能( Bumperボタン以外は省略 ).
            if (_controllerActions.Bumper.IsPressed())
            {
                Debug.Log("Update : IsBumperPressed");
            }

            // コントローラの座標と回転はワールド座標で取得される.
            //Debug.Log($"Controller Position {_controllerActions.Position.ReadValue<Vector3>()}");
            //Debug.Log($"Controller Rotation {_controllerActions.Rotation.ReadValue<Quaternion>().eulerAngles}");
        }


        private void HandleOnBumper(InputAction.CallbackContext obj)
        {
            bool bumperDown = obj.ReadValueAsButton();
            Debug.Log($"The Bumper is pressed down {bumperDown}");
        }

    }

}

サンプルコードのフル版

using UnityEngine;
using UnityEngine.InputSystem;


namespace Sandbox.Controller
{
    /// <summary>
    /// コントローラ入力サンプル.
    /// </summary>
    public class ControllerInputSample : MonoBehaviour
    {

        private MagicLeapInputs _mlInputs;
        private MagicLeapInputs.ControllerActions _controllerActions;
        
        
        private void Start()
        {
            // 新しいインスタンスを作成し、起動.
            _mlInputs = new MagicLeapInputs();
            _mlInputs.Enable();

            // 各入力のイベントハンドラを登録.
            _controllerActions = new MagicLeapInputs.ControllerActions(_mlInputs);
            _controllerActions.Bumper.started += HandleOnBumperStarted;
            _controllerActions.Bumper.performed += HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled += HandleOnBumperCanceled;

            _controllerActions.Menu.started += HandleOnMenuStarted;
            _controllerActions.Menu.performed += HandleOnMenuPerformed;
            _controllerActions.Menu.canceled += HandleOnMenuCanceled;

            _controllerActions.Trigger.started += HandleOnTriggerStarted;
            _controllerActions.Trigger.performed += HandleOnTriggerPerformed;
            _controllerActions.Trigger.canceled += HandleOnTriggerCanceled;

            _controllerActions.TouchpadClick.started += HandleOnTouchpadClickStarted;
            _controllerActions.TouchpadClick.performed += HandleOnTouchpadClickPerformed;
            _controllerActions.TouchpadClick.canceled += HandleOnTouchpadClickCanceled;

            _controllerActions.TouchpadTouch.started += HandleOnTouchpadTouchStarted;
            _controllerActions.TouchpadTouch.performed += HandleOnTouchpadTouchPerformed;
            _controllerActions.TouchpadTouch.canceled += HandleOnTouchpadTouchCanceled;

            _controllerActions.TouchpadForce.started += HandleOnTouchpadForceStarted;
            _controllerActions.TouchpadForce.performed += HandleOnTouchpadForcePerformed;
            _controllerActions.TouchpadForce.canceled += HandleOnTouchpadForceCanceled;

            _controllerActions.TouchpadPosition.started += HandleOnTouchpadPositionStarted;
            _controllerActions.TouchpadPosition.performed += HandleOnTouchpadPositionPerformed;
            _controllerActions.TouchpadPosition.canceled += HandleOnTouchpadPositionCanceled;

            _controllerActions.IsTracked.started += HandleOnIsTrackedStarted;
            _controllerActions.IsTracked.performed += HandleOnIsTrackedPerformed;
            _controllerActions.IsTracked.canceled += HandleOnIsTrackedCanceled;
        }
    

        private void OnDestroy()
        {
            // 登録していたハンドラを削除.
            _controllerActions.Bumper.started -= HandleOnBumperStarted;
            _controllerActions.Bumper.performed -= HandleOnBumperPerformed;
            _controllerActions.Bumper.canceled -= HandleOnBumperCanceled;

            _controllerActions.Menu.started -= HandleOnMenuStarted;
            _controllerActions.Menu.performed -= HandleOnMenuPerformed;
            _controllerActions.Menu.canceled -= HandleOnMenuCanceled;

            _controllerActions.Trigger.started -= HandleOnTriggerStarted;
            _controllerActions.Trigger.performed -= HandleOnTriggerPerformed;
            _controllerActions.Trigger.canceled -= HandleOnTriggerCanceled;

            _controllerActions.TouchpadClick.started -= HandleOnTouchpadClickStarted;
            _controllerActions.TouchpadClick.performed -= HandleOnTouchpadClickPerformed;
            _controllerActions.TouchpadClick.canceled -= HandleOnTouchpadClickCanceled;

            _controllerActions.TouchpadTouch.started -= HandleOnTouchpadTouchStarted;
            _controllerActions.TouchpadTouch.performed -= HandleOnTouchpadTouchPerformed;
            _controllerActions.TouchpadTouch.canceled -= HandleOnTouchpadTouchCanceled;
            
            _controllerActions.TouchpadForce.started -= HandleOnTouchpadForceStarted;
            _controllerActions.TouchpadForce.performed -= HandleOnTouchpadForcePerformed;
            _controllerActions.TouchpadForce.canceled -= HandleOnTouchpadForceCanceled;
            
            _controllerActions.TouchpadPosition.started -= HandleOnTouchpadPositionStarted;
            _controllerActions.TouchpadPosition.performed -= HandleOnTouchpadPositionPerformed;
            _controllerActions.TouchpadPosition.canceled -= HandleOnTouchpadPositionCanceled;
            
            _controllerActions.IsTracked.started -= HandleOnIsTrackedStarted;
            _controllerActions.IsTracked.performed -= HandleOnIsTrackedPerformed;
            _controllerActions.IsTracked.canceled -= HandleOnIsTrackedCanceled;

            // 入力の購読を終了.
            _mlInputs.Dispose();
        }


        private void Update()
        {
            // Update で直接確認することも可能( Bumperボタン以外は省略 ).
            if (_controllerActions.Bumper.IsPressed())
            {
                Debug.Log("Update : IsBumperPressed");
            }

            // コントローラの座標と回転はワールド座標で取得される.
            //Debug.Log($"Controller Position {_controllerActions.Position.ReadValue<Vector3>()}");
            //Debug.Log($"Controller Rotation {_controllerActions.Rotation.ReadValue<Quaternion>().eulerAngles}");
        }


        #region --- Menu Button ---
        
        private void HandleOnMenuStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is started");
        }


        private void HandleOnMenuPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is performed");
        }


        private void HandleOnMenuCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The Menu is canceled");
        }
        
        #endregion --- Menu Button ---


        #region --- Bumper Button ---
        
        private void HandleOnBumperStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Bumper is started.");
        }
        

        private void HandleOnBumperPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is performed.");
        }


        private void HandleOnBumperCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Bumper is canceled.");
        }
        
        #endregion --- Bumper Button ---

        
        #region --- Trigger ---

        private void HandleOnTriggerStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger started value : {obj.ReadValue<float>()}");
        }


        private void HandleOnTriggerPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger performed value : {obj.ReadValue<float>()}");
        }


        private void HandleOnTriggerCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Trigger canceled value : {obj.ReadValue<float>()}");
        }
        
        #endregion --- Trigger ---
        
        
        #region --- Touchpad Click ---

        private void HandleOnTouchpadClickStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click started {obj.ReadValueAsButton()}");
        }


        private void HandleOnTouchpadClickPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click performed {obj.ReadValueAsButton()}");
        }


        private void HandleOnTouchpadClickCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Click canceled {obj.ReadValueAsButton()}");
        }

        #endregion --- Touchpad Click ---

        
        #region --- Touchpad Touch ---

        private void HandleOnTouchpadTouchStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch started.");
        }


        private void HandleOnTouchpadTouchPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch performed.");
        }

        
        private void HandleOnTouchpadTouchCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The TouchPad Touch canceled.");
        }

        #endregion --- Touchpad Touch ---
        
        
        #region --- Touchpad Force ---

        private void HandleOnTouchpadForceStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force started.");
        }

        
        private void HandleOnTouchpadForcePerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force performed.");
        }

        
        private void HandleOnTouchpadForceCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The Touchpad Force canceled.");
        }
        
        #endregion --- Touchpad Force ---
        
        
        #region --- Touchpad Position ---
        
        /// <summary>
        /// 中心座標が0のタッチパッド上の XY 座標値.
        /// </summary>
        private void HandleOnTouchpadPositionStarted(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position started value {obj.ReadValue<Vector2>()}");
        }

        
        private void HandleOnTouchpadPositionPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position performed value {obj.ReadValue<Vector2>()}");
        }

        
        private void HandleOnTouchpadPositionCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log($"The Touchpad Position canceled value {obj.ReadValue<Vector2>()}");
        }

        #endregion --- Touchpad Position ---
        
        
        #region --- IsTracked ---

        /// <summary>
        /// コントローラが接続しているか判定.
        /// なぜかはわからんが Started は呼ばれない.
        /// 接続したときに Performed が一度呼ばれる.
        /// 切断したときに Canceled が一度呼ばれる.
        /// 常に把握したい場合は Update() なりで常時監視したほうがいいかも?
        /// </summary>
        private void HandleOnIsTrackedStarted(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked started.");
        }
        

        private void HandleOnIsTrackedPerformed(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked performed.");
        }


        private void HandleOnIsTrackedCanceled(InputAction.CallbackContext obj)
        {
            Debug.Log("The IsTracked canceled.");
        }
        
        #endregion --- IsTracked ---
    }
}


触ってみた感想としてはボタン系の入力は基本イベント購読の形で行うのがよいかと思います、コントローラの座標や回転はイベント購読では取得できなかったのでUpdate()などで都度取得するのがよいかなと思います。

今後以下のリポジトリで触ってみたサンプルとかを増やしていく予定です github.com