【Unity】【LeapMotion】③左右の手を分けてジェスチャ取得(ついでにトラッキング開始/終了も)
②ではとりあえず、片手での握る/離すジェスチャができました。
今度は左右分けて、どっちが開いて閉じたかを取得したい。
ということで、前回使った
「MotionCtrl.cs」
「IMotionCallback.cs」
を改造してみる。
「MotionCtrl.cs」
using Leap; using UnityEngine; using System.Collections.Generic; using System.Linq; public class MotionCtrl : MonoBehaviour { public List<GameObject> motionCtrlObjectList; private List<IMotionCallback> motionCtrlList; private int motionCtrlCount; private Controller leapCtrl; private Frame leapFrame; private List<Hand> handList; private Hand R_Hand, L_Hand; private bool isTracking; private bool isGrabbed_R, isGrabbed_L; private bool lastTrackingStatus; private bool lastGrabbedStatus_R, lastGrabbedStatus_L; private Vector3 convertedValue = new Vector3(0, 0, 0); private Vector3 handPosition_R, handPosition_L; /* public Vector3 HandPosition { get { return handPosition; } } */ private void Start() { // Trackingと手の状態変化を返す対象のClass. motionCtrlList = motionCtrlObjectList.Select(ctrlObject => ctrlObject.GetComponent<IMotionCallback>()).ToList(); motionCtrlCount = motionCtrlList.Count - 1; // App起動時にLeapMotionに接続. leapCtrl = new Controller(); // StartConnectionの実行は必要? leapCtrl.StartConnection(); isTracking = false; isGrabbed_R = false; isGrabbed_L = false; lastTrackingStatus = false; lastGrabbedStatus_R = false; lastGrabbedStatus_L = false; } private void Update() { leapFrame = leapCtrl.Frame(); handList = leapFrame.Hands; isTracking = (handList.Count > 0); if (isTracking != lastTrackingStatus) { // Trackingの開始・停止をCallbackで通知. if (isTracking) { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnTrackingStarted(); } } else { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnTrackingStopped(); } // 手の位置をリセット. handPosition_R.Set(0, 0, 0); handPosition_L.Set(0, 0, 0); } lastTrackingStatus = isTracking; } if (!isTracking) { // Tracking中でなければ手の位置などは取得しない. return; } for(int NumHands = 0; NumHands < handList.Count; NumHands++) { if (handList[NumHands].IsRight) { // Tracking中なら手(Hand0)の平の座標値を取得する. handPosition_R = ConvertToUnityVector3(handList[NumHands].PalmPosition); // 手を握っているか(誤検知を考慮して開いている指の本数が1以下ならTrue). isGrabbed_R = (handList[NumHands].Fingers.Where(finger => finger.IsExtended).Count() <= 1); if (isGrabbed_R != lastGrabbedStatus_R) { if (isGrabbed_R) { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnRightHandGrabbed(); } } else { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnRightHandReleased(); } } lastGrabbedStatus_R = isGrabbed_R; } } if (handList[NumHands].IsLeft) { // Tracking中なら手(Hand0)の平の座標値を取得する. handPosition_L = ConvertToUnityVector3(handList[NumHands].PalmPosition); // 手を握っているか(誤検知を考慮して開いている指の本数が1以下ならTrue). isGrabbed_L = (handList[NumHands].Fingers.Where(finger => finger.IsExtended).Count() <= 1); if (isGrabbed_L != lastGrabbedStatus_L) { if (isGrabbed_L) { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnLeftHandGrabbed(); } } else { for (var i = motionCtrlCount; i >= 0; i--) { motionCtrlList[i].OnLeftHandReleased(); } } lastGrabbedStatus_L = isGrabbed_L; } } } } private void OnApplicationQuit() { // Appの終了時は切断する. leapCtrl.StopConnection(); leapCtrl.Dispose(); } private Vector3 ConvertToUnityVector3(Vector originalValue) { // Leap.VectorからUnityのVector3に変換する. convertedValue.x = originalValue.x; convertedValue.y = originalValue.y; convertedValue.z = originalValue.z; return convertedValue; } }
変更点は、handList[0](最初に認識した手 二番目ならhandList[1])のところをisLeft/isRightで左右に分けて、コールバックも分けたところです。それに伴い変数も増やしてforで回しています。
そしてコールバックがこちら
「IMotionCallback.cs」
using System.Collections; using System.Collections.Generic; using UnityEngine; public interface IMotionCallback { void OnTrackingStarted(); void OnTrackingStopped(); void OnRightHandGrabbed(); void OnLeftHandGrabbed(); void OnRightHandReleased(); void OnLeftHandReleased(); }
それを使うには、前回と同様に、
GetGesture.cs
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class GetGesture : MonoBehaviour, IMotionCallback { public void OnTrackingStarted() { Debug.Log("StartTracking Hand"); } public void OnTrackingStopped() { Debug.Log("StopTracking Hand"); } public void OnLeftHandGrabbed() { Debug.Log("LeftHandGrabbed"); } public void OnLeftHandReleased() { Debug.Log("LeftHandReleased"); } public void OnRightHandGrabbed() { Debug.Log("RightHandGrabbed"); } public void OnRightHandReleased() { Debug.Log("RightHandReleased"); } }
こんな感じで使います。
この「GetGesture.cs」のついたオブジェクトを「MotionCtrl.cs」の「motionCtrlObjectList」にポイすればOK
今回は手本体につけていた「GetGesture.cs」をCameraに移動しました。
左右でグーパーできた!!!
(人差し指の誤検知は気にしない)(誤検知多いときは部屋を暗くするといいぞ!)