さっそくですが、デモです。

左手のジェスチャー認識でUIのアクティブを切り替えて、
現実空間に表示したボタンのようなものを右手人差し指で押すと、
インタラクションを伴ってカウントが進みます。

とてもシンプルに実装可能なのですが、
知らないと実装するまで少々時間を使います。
ですので、どなたかのお役に立てるようメモを残しておきます。


バージョン情報

Unity 2019.3.4f1
Lumin OS v0.98.10
Lumin SDK 0.24.1


下準備

ビルドまでの環境構築は下記リンク参照です。 
https://gaprot.jp/2020/05/11/magicleap-dev-environment/

今回のデモのボタンを押す機能の仕組みとしては
指にSphereを追従させて物体との衝突判定を取得し、
任意の処理を走らせている形となります。

そこで、まずはSphereをHierarchyに配置します。
Inspectorの設定は下記の通りです。
注意点としてはスケールが指の先端のサイズ程度になっていることぐらいです。

あとは、触られる側のオブジェクトにも通常の当たり判定と同様に
コライダーを付けてIsTriggerをオンにすればOKです。


コード

下記が、手でUIをアクティブ、非アクティブにするコード及び、
指にSphereを追従させる処理の全文です。

using UnityEngine;
using UnityEngine.XR.MagicLeap;

    /// <summary>
    /// HandTrackingでオブジェクトをタッチ操作してみる UIのアクティブもジェスチャーで切り替え
    /// </summary>
    public class HandDemoManager  : MonoBehaviour
    {
        [SerializeField] private MLHandTracking.HandKeyPose _activeUIKeyPose;
        [SerializeField] private MLHandTracking.HandKeyPose _inactiveUIKeyPose;
        [SerializeField] private MLHandTracking.HandKeyPose _selectUIKeyPose;

        [SerializeField] private GameObject _uiObject;
        [SerializeField] private GameObject _handCollision;

        //手のジェスチャーに応じた
        //認識率
        private float _keyPoseConfidenceValue = 0.6f;

        private MLResult result;
        
        private void Start()
        {
            //HandTracking Start
            result = MLHandTracking.Start();

            //ハンドトラッキング機能が正しく立ち上がってるかチェック
            if (!result.IsOk)
            {
                return;
            }

            //左手
            MLHandTracking.Hand mlLHand = MLHandTracking.Left;

            //右手
            MLHandTracking.Hand mlRHand = MLHandTracking.Right;

            //手を登録
            MLHandTracking.KeyposeManager keyPoseManager = new MLHandTracking.KeyposeManager(mlLHand, mlRHand);

            //---------------------------------------------------------------
            // 任意のポーズのコールバック 右手
            //---------------------------------------------------------------

            //右手のポーズ変化のコールバック UIを表示
            keyPoseManager.OnKeyPoseBegin += (pose, type) =>
            {
                if (type == MLHandTracking.HandType.Left && pose == _activeUIKeyPose)
                {
                    _uiObject.SetActive(true);
                }
                
                if (type == MLHandTracking.HandType.Left && pose == _inactiveUIKeyPose)
                {
                    _uiObject.SetActive(false);
                }
            };
        }

        private void Update()
        {
            //ハンドトラッキング機能が正しく立ち上がってるかチェック
            if (!result.IsOk)
            {
                return;
            }

            //任意のポーズ時に指先に当たり判定を与える
            if (MLHandTracking.Right.KeyPose == _selectUIKeyPose && MLHandTracking.Right.HandKeyPoseConfidence >= _keyPoseConfidenceValue)
            {
                //任意の手の形状であればアクティブに → すなわち、当たり判定追加
                _handCollision.SetActive(true);
                _handCollision.gameObject.transform.position = MLHandTracking.Right.Index.Tip.Position;
            }
            else
            {
                //任意の手の形状でなければ非アクティブ → すなわち、当たり判定消去
                _handCollision.SetActive(false);
            }
        }
    }

MLHandTracking

ハンドラッキングを使う際にMLHandTrackingというクラスを使います。
SDKのバージョンが上がってクラス名が変わりましたので
過去のバージョンを使っている場合は注意が必要です。

手の状態変化のコールバックを使用する際には、
下記のように手にまつわるクラスのインスタンスをStart関数で
生成して利用します。

 //左手
 MLHandTracking.Hand mlLHand = MLHandTracking.Left;

 //右手
 MLHandTracking.Hand mlRHand = MLHandTracking.Right;

 //手を登録
 MLHandTracking.KeyposeManager keyPoseManager = new MLHandTracking.KeyposeManager(mlLHand, mlRHand);

下記が手の状態変化のコールバックの利用箇所です。
指定したポーズへの変化が始まった際(指定したポーズになった瞬間)に
任意の処理が呼ばれます。

//---------------------------------------------------------------
// 任意のポーズのコールバック 右手
//---------------------------------------------------------------

//左手のポーズ変化のコールバック UIを表示
keyPoseManager.OnKeyPoseBegin += (pose, type) =>
{
    if (type == MLHandTracking.HandType.Left && pose == _activeUIKeyPose)
    {
        _uiObject.SetActive(true);
    }

    if (type == MLHandTracking.HandType.Left && pose == _inactiveUIKeyPose)
    {
        _uiObject.SetActive(false);
    }
};

手の状態判定の利用として、
コールバック以外に手の状態をBool値として利用する方法があります。

今回のデモにおいても、
指にSphereが追従する機能の箇所で実際に利用しています。
MLHandTracking.Right.KeyPose
任意のポーズかどうかの判定が可能です。

 //任意のポーズ時に指先に当たり判定を与える
 if (MLHandTracking.Right.KeyPose == _selectUIKeyPose && MLHandTracking.Right.HandKeyPoseConfidence >= _keyPoseConfidenceValue)
 {
     //任意の手の形状であればアクティブに → すなわち、当たり判定追加
     _handCollision.SetActive(true);
     _handCollision.gameObject.transform.position = MLHandTracking.Right.Index.Tip.Position;
 }
 else
 {
     //任意の手の形状でなければ非アクティブ → すなわち、当たり判定消去
     _handCollision.SetActive(false);
 }

MLHandTracking.Right.HandKeyPoseConfidenceというパラメータを
利用すれば、手のジェスチャーの認識具合で判定を行うことも可能です。

ジェスチャーには下記の8種類が用意されています。

上記画像のジェスチャーがそれぞれ対応するEnumのステート名は左から、
下記画像の昇順通りです。

最後に

環境構築から開発に至るまで苦労したのも相まって、
MagicLeapの開発とても楽しいです。
SDKやOSの更新もどんどん行われているのでこれからも期待大ですね。



ギャップロを運営しているアップフロンティア株式会社では、一緒に働いてくれる仲間を随時、募集しています。 興味がある!一緒に働いてみたい!という方は下記よりご応募お待ちしております。
採用情報をみる