貼幾個直接能在Unity(2017.4.27f1)上測試的代碼
1.測試手勢的
1 using Leap; 2 using System.Collections; 3 using System.Collections.Generic; 4 using UnityEngine; 5 using Leap.Unity; 6 /// <summary> 7 /// 旋轉/縮放/移動 8 /// </summary> 9 public class ControlAnimation : MonoBehaviour 10 { 11 12 LeapProvider provider; 13 public HandModelBase leftHandModel; 14 public HandModelBase rightHandModel; 15 private const float rotate_sensitive = 1500f; //旋轉靈敏度 16 private const float displacement_sensitive = 0.015f; //位移靈敏度 17 private const float rotate_initial_value = 0f; //旋轉初始位置值 18 19 /// <summary> 20 /// 判斷條件 盡量勿動 21 /// </summary> 22 const float smallestVelocity = 0.1f; 23 const float deltaVelocity = 0.000001f; 24 const float deltaCloseFinger = 0.06f; 25 26 void Start() 27 { 28 provider = FindObjectOfType<LeapProvider>() as LeapProvider; 29 } 30 31 32 void Update() 33 { 34 Scale(); 35 Rotation(); 36 Position(); 37 } 38 39 40 /// <summary> 41 /// 縮小 42 /// </summary> 43 public void Scale() 44 { 45 Frame frame = provider.CurrentFrame; 46 foreach (Hand hand in frame.Hands) 47 { 48 if (isOpenFullHand(hand)) 49 { 50 Debug.Log("大"); 51 52 //Vector3 value = transform.localScale; 53 //value += new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); 54 //// Debug.Log(value); 55 //transform.localScale = value; 56 transform.Translate(Vector3.forward * Time.deltaTime * 5); 57 } 58 if (isCloseHand(hand)) 59 { 60 //Debug.Log("小"); 61 //Vector3 value = transform.localScale; 62 //value -= new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); 63 //// Debug.Log(value); 64 65 //transform.localScale = value; 66 } 67 } 68 } 69 70 71 /// <summary> 72 /// 旋轉 73 /// </summary> 74 public void Rotation() 75 { 76 Frame frame = provider.CurrentFrame; 77 foreach (Hand hand in frame.Hands) 78 { 79 if (hand.IsLeft || hand.IsRight) 80 { 81 Vector3 value = transform.localEulerAngles; 82 value = new Vector3(/*hand.PalmPosition.y * rotate_sensitive + rotate_initial_value*/0, hand.PalmPosition.x * rotate_sensitive + rotate_initial_value, 0); 83 transform.localEulerAngles = value; 84 } 85 else 86 { 87 hand.PalmPosition.y = transform.localEulerAngles.x; 88 hand.PalmPosition.x = transform.localEulerAngles.y; 89 } 90 } 91 } 92 93 94 /// <summary> 95 /// 位移 96 /// </summary> 97 public void Position() 98 { 99 Frame frame = provider.CurrentFrame; 100 foreach (Hand hand in frame.Hands) 101 { 102 if (hand.IsLeft || hand.IsRight) 103 { 104 if (isMoveLeft(hand)) 105 { 106 transform.localPosition = new Vector3(hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; 107 } 108 if (isMoveRight(hand)) 109 { 110 transform.localPosition = new Vector3(-hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; 111 } 112 } 113 } 114 115 } 116 117 118 protected bool isMoveRight(Hand hand)// 手划向右邊 119 { 120 Debug.Log("左滑"); 121 return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand); 122 } 123 124 125 protected bool isMoveLeft(Hand hand) // 手划向左邊 126 { 127 Debug.Log("右滑"); 128 //x軸移動的速度 deltaVelocity = 0.7f isStationary (hand) 判斷hand是否禁止 129 return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand); 130 } 131 132 protected bool isStationary(Hand hand)// 固定不動的 133 { 134 return hand.PalmVelocity.Magnitude < smallestVelocity; 135 } 136 137 protected bool isCloseHand(Hand hand) //是否握拳 138 { 139 Debug.Log("握拳"); 140 List<Finger> listOfFingers = hand.Fingers; 141 int count = 0; 142 for (int f = 0; f < listOfFingers.Count; f++) 143 { //循環遍歷所有的手~~ 144 Finger finger = listOfFingers[f]; 145 if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger) // Magnitude 向量的長度 。是(x*x+y*y+z*z)的平方根。 //float deltaCloseFinger = 0.05f; 146 { 147 count++; 148 // if (finger.Type == Finger.FingerType.TYPE_THUMB) 149 // Debug.Log ((finger.TipPosition - hand.PalmPosition).Magnitude); 150 } 151 } 152 return (count == 5); 153 } 154 155 protected bool isOpenFullHand(Hand hand) //手掌全展開~ 156 { 157 Debug.Log("展開"); 158 //Debug.Log (hand.GrabStrength + " " + hand.PalmVelocity + " " + hand.PalmVelocity.Magnitude); 159 return hand.GrabStrength == 0; 160 } 161 }
2.食指點擊UI按鈕的,需要給按鈕加個碰撞(觸發)
1 using System.Collections; 2 using System.Collections.Generic; 3 using Leap; 4 using Leap.Unity; 5 using UnityEngine; 6 using UnityEngine.UI; 7 /// <summary> 8 /// 手指點擊 9 /// </summary> 10 public class JudgeHandDetector : MonoBehaviour 11 { 12 13 public Transform[] bonesL; 14 public Transform[] bonesR; 15 public HandModelBase leftHand; 16 public HandModelBase rightHand; 17 18 List<HandModelBase> handModelList = new List<HandModelBase>(); 19 // Update is called once per frame 20 void Update() 21 { 22 23 // 如果兩個手都沒有識別 清空 list 表 24 if (!leftHand.IsTracked) 25 { 26 if (handModelList.Contains(leftHand)) 27 { 28 handModelList.Remove(leftHand); 29 } 30 } 31 if (!rightHand.IsTracked) 32 { 33 if (handModelList.Contains(rightHand)) 34 { 35 handModelList.Remove(rightHand); 36 } 37 } 38 // 鼠標移動 根據 list[0] 去操作,判斷識別手的先后關系 39 if (leftHand != null && leftHand.IsTracked) 40 { 41 if (!handModelList.Contains(leftHand)) 42 { 43 handModelList.Add(leftHand); 44 } 45 } 46 if (rightHand != null && rightHand.IsTracked) 47 { 48 if (!handModelList.Contains(rightHand)) 49 { 50 handModelList.Add(rightHand); 51 } 52 } 53 if (handModelList.Count > 0) 54 { 55 IndexDetector(); 56 } 57 } 58 Ray ray; 59 /// <summary> 60 /// 左右手食指識別 進入相同的處理邏輯 61 /// </summary> 62 void IndexDetector() 63 { 64 if (handModelList[0] == leftHand) 65 { 66 JudgeIndexDetector(bonesL); 67 } 68 else 69 { 70 JudgeIndexDetector(bonesR); 71 } 72 } 73 74 /// <summary> 75 /// 判斷食指識別 76 /// </summary> 77 /// <param name="bones"></param> 78 void JudgeIndexDetector(Transform[] bones) 79 { 80 if (bones[1].position.z > bones[0].position.z && bones[1].position.z > bones[2].position.z && 81 bones[1].position.z > bones[3].position.z && bones[1].position.z > bones[4].position.z) 82 { 83 print("這個傻逼伸出了邪惡的食指"); 84 DealRay(bones[1].position); 85 } 86 } 87 /// <summary> 88 /// 處理射線得到的信息 89 /// </summary> 90 void DealRay(Vector3 RayPointV3) 91 { 92 Vector2 screenPos = Camera.main.WorldToScreenPoint(RayPointV3); 93 ray = Camera.main.ScreenPointToRay(screenPos); 94 RaycastHit[] hit = Physics.RaycastAll(ray, 2000f, 1 << LayerMask.NameToLayer("UI")); ; 95 if (hit.Length > 0) 96 { 97 for (int i = 0; i < hit.Length; i++) 98 { 99 Debug.Log("檢測到物體" + hit[i].collider.name); 100 BtnEvent(hit[i].transform); 101 } 102 } 103 } 104 105 106 void BtnEvent(Transform btn) 107 { 108 switch (btn.name) 109 { 110 case "Button1": 111 btn.GetComponentInChildren<Text>().text = "把你的臟手從 Button1 上拿開"; 112 break; 113 case "Button2": 114 break; 115 case "Button3": 116 break; 117 case "Button4": 118 break; 119 case "Button5": 120 break; 121 case "Button6": 122 break; 123 default: 124 break; 125 } 126 } 127 }
3.手部運動測試
1 using System.Collections; 2 using System.Collections.Generic; 3 using Leap; 4 using Leap.Unity; 5 using UnityEngine; 6 /// <summary> 7 /// 手部運動測試 8 /// </summary> 9 public class JudgeSwipe : MonoBehaviour 10 { 11 public HandModelBase leftHandModel; 12 [Tooltip("Velocity (m/s) move toward ")] 13 protected float deltaVelocity = 0.7f; 14 //這里傳進來你要打開的手指 緊握手指 {} 傳一個手指{Finger.FingerType.TYPE_RING}...以此類推,當傳進5個值得時候代表 手張開,當傳進0個值的時候代表 握手 15 Finger.FingerType[] arr = { Finger.FingerType.TYPE_INDEX, Finger.FingerType.TYPE_MIDDLE }; 16 17 // Update is called once per frame 18 void Update() 19 { 20 if (!leftHandModel.IsTracked) return; 21 Hand leftHand = leftHandModel.GetLeapHand(); 22 //if (IsMoveLeft(leftHand)) 23 //{ 24 // print("左手向左滑動"); 25 //} 26 //if (IsMoveRight(leftHand)) 27 //{ 28 // print("左手向右滑動"); 29 //} 30 //if (IsMoveUp(leftHand)) 31 //{ 32 // print("左手向上滑動"); 33 //} 34 //if (IsMoveDown(leftHand)) 35 //{ 36 // print("左手向下滑動"); 37 //} 38 39 //if (IsCloseHand(leftHand)) 40 //{ 41 // print("握拳"); 42 //} 43 //if (IsOpenFullHand(leftHand)) 44 //{ 45 // print("張手"); 46 //} 47 //if (CheckFingerCloseToHand(leftHand)) 48 //{ 49 // print("四指指向掌心"); 50 //} 51 52 //if (CheckFingerOpenToHand(leftHand, arr)) 53 //{ 54 // print("ok"); 55 //} 56 } 57 /// <summary> 58 /// 這個方法用來擴展哪幾個手指打開,這里傳進來你要判斷是否打開的手指 緊握手指 {} 傳一個手指{Finger.FingerType.TYPE_RING}... 59 /// 以此類推,當傳進5個值得時候代表 手張開,當傳進0個值的時候代表 握手 60 /// </summary> 61 /// <param name="hand"></param> 62 /// <param name="arr"></param> 63 /// <returns></returns> 64 bool CheckFingerOpenToHand(Hand hand, Finger.FingerType[] fingerTypesArr, float deltaCloseFinger = 0.05f) 65 { 66 List<Finger> listOfFingers = hand.Fingers; 67 float count = 0; 68 // 遍歷5個手指 69 for (int f = 0; f < listOfFingers.Count; f++) 70 { 71 Finger finger = listOfFingers[f]; 72 // 判讀每個手指的指尖位置和掌心位置的長度是不是小於某個值,以判斷手指是否貼着掌心 73 if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger) 74 { 75 // 如果傳進來的數組長度是0,有一個手指那么 count + 1,continue 跳出,不執行下面數組長度不是0 的邏輯 76 if (fingerTypesArr.Length == 0) 77 { 78 count++; 79 continue; 80 } 81 // 傳進來的數組長度不是 0, 82 for (int i = 0; i < fingerTypesArr.Length; i++) 83 { 84 // 假如本例子傳進來的是食指和中指,邏輯走到這里,如果你的食指是緊握的,下面會判斷這個手指是不是食指,返回 false 85 if (finger.Type == fingerTypesArr[i]) 86 { 87 return false; 88 } 89 else 90 { 91 count++; 92 } 93 } 94 } 95 } 96 if (fingerTypesArr.Length == 0) 97 { 98 return count == 5; 99 } 100 // 這里除以length 是因為上面數組在每次 for 循環 count ++ 會執行 length 次 101 return (count / fingerTypesArr.Length == 5 - fingerTypesArr.Length); 102 } 103 104 /// <summary> 105 /// 判斷是否抓取 106 /// </summary> 107 /// <param name="hand"></param> 108 /// <returns></returns> 109 bool isGrabHand(Hand hand) 110 { 111 return hand.GrabStrength > 0.8f; 112 } 113 114 /// <summary> 115 /// 判斷是不是握拳 116 /// </summary> 117 /// <param name="hand"></param> 118 /// <returns></returns> 119 bool IsCloseHand(Hand hand) 120 { 121 List<Finger> listOfFingers = hand.Fingers; 122 int count = 0; 123 for (int f = 0; f < listOfFingers.Count; f++) 124 { 125 Finger finger = listOfFingers[f]; 126 if ((finger.TipPosition - hand.PalmPosition).Magnitude < 0.05f) 127 { 128 count++; 129 } 130 } 131 return (count == 4); 132 } 133 134 /// <summary> 135 /// 判斷手指是否全張開 136 /// </summary> 137 /// <param name="hand"></param> 138 /// <returns></returns> 139 bool IsOpenFullHand(Hand hand) 140 { 141 return hand.GrabStrength == 0; 142 } 143 144 /// <summary> 145 /// 手滑向左邊 146 /// </summary> 147 /// <param name="hand"></param> 148 /// <returns></returns> 149 protected bool IsMoveLeft(Hand hand) // 手划向左邊 150 { 151 //x軸移動的速度 deltaVelocity = 0.7f 152 return hand.PalmVelocity.x < -deltaVelocity; 153 } 154 155 /// <summary> 156 /// 手滑向右邊 157 /// </summary> 158 /// <param name="hand"></param> 159 /// <returns></returns> 160 protected bool IsMoveRight(Hand hand) 161 { 162 return hand.PalmVelocity.x > deltaVelocity; 163 } 164 165 /// <summary> 166 /// 手滑向上邊 167 /// </summary> 168 /// <param name="hand"></param> 169 /// <returns></returns> 170 protected bool IsMoveUp(Hand hand) 171 { 172 return hand.PalmVelocity.y > deltaVelocity; 173 } 174 175 /// <summary> 176 /// 手滑向下邊 177 /// </summary> 178 /// <param name="hand"></param> 179 /// <returns></returns> 180 protected bool IsMoveDown(Hand hand) 181 { 182 return hand.PalmVelocity.y < -deltaVelocity; 183 } 184 185 186 /// <summary> 187 /// 判斷四指是否靠向掌心 188 /// </summary> 189 /// <param name="hand"></param> 190 /// <returns></returns> 191 bool CheckFingerCloseToHand(Hand hand) 192 { 193 List<Finger> listOfFingers = hand.Fingers; 194 int count = 0; 195 for (int f = 0; f < listOfFingers.Count; f++) 196 { 197 Finger finger = listOfFingers[f]; 198 if ((finger.TipPosition - hand.PalmPosition).Magnitude < 0.05f) 199 { 200 if (finger.Type == Finger.FingerType.TYPE_THUMB) 201 { 202 return false; 203 } 204 else 205 { 206 count++; 207 } 208 } 209 } 210 return (count == 4); 211 } 212 213 214 }
using Leap; using Leap.Unity; using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 物體跟隨左手移動 /// </summary> public class LeapBehavior : MonoBehaviour { LeapProvider provider; void Start() { provider = FindObjectOfType<LeapProvider>() as LeapProvider; } void Update() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft) { transform.position = hand.PalmPosition.ToVector3() + hand.PalmNormal.ToVector3() * (transform.localScale.y * .5f + .02f); transform.rotation = hand.Basis.CalculateRotation(); } } } }
4.觸碰改變顏色
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using Leap; 5 using Leap.Unity; 6 using System; 7 /// <summary> 8 /// 手指攝取顏色 9 /// </summary> 10 public class JudgeChangeColor : MonoBehaviour 11 { 12 public Color c; 13 public static Color selectedColor; 14 public bool selectable = false; 15 16 void OnTriggerStay(Collider c) 17 { 18 if (c.gameObject.transform.parent.name.Equals("index")) 19 { 20 if (this.selectable) 21 { 22 JudgeChangeColor.selectedColor = this.c; 23 this.transform.Rotate(Vector3.up); 24 return; 25 } 26 transform.gameObject.GetComponent<MeshRenderer>().material.color = JudgeChangeColor.selectedColor; 27 } 28 } 29 30 }
5.拇指和食指捏住改變縮放
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using Leap; 5 using Leap.Unity; 6 using System; 7 /// <summary> 8 /// 手指攝取顏色 9 /// </summary> 10 public class CubeInteraction : MonoBehaviour { 11 public Transform tran; 12 bool isHold = false; 13 Vector3 offset; 14 void Start() 15 { 16 17 } 18 public Transform[] bonesL; 19 public Transform[] bonesR; 20 public HandModelBase leftHand; 21 public HandModelBase rightHand; 22 23 List<HandModelBase> handModelList = new List<HandModelBase>(); 24 25 void Update() 26 { 27 //如果兩個手都沒有識別 清空列表 28 if (!leftHand.IsTracked) 29 { 30 if (handModelList.Contains(leftHand)) 31 { 32 handModelList.Remove(leftHand); 33 } 34 } 35 if (!rightHand.IsTracked) 36 { 37 if (handModelList.Contains(rightHand)) 38 { 39 handModelList.Remove(rightHand); 40 } 41 } 42 //鼠標移動 根據list[0]去操作,判斷識別手的先后關系 43 if (leftHand != null && leftHand.IsTracked) 44 { 45 if (!handModelList.Contains(leftHand)) 46 { 47 handModelList.Add(leftHand); 48 } 49 } 50 if (rightHand != null && rightHand.IsTracked) 51 { 52 if (!handModelList.Contains(rightHand)) 53 { 54 handModelList.Add(rightHand); 55 } 56 } 57 if (handModelList.Count > 0) 58 { 59 JudgeHand(); 60 } 61 } 62 63 private void JudgeHand() 64 { 65 if (Vector3.Distance(bonesL[0].position, bonesL[1].position) < 0.02f && 66 Vector3.Distance(bonesR[0].position, bonesR[1].position) < 0.02f) 67 { 68 Debug.Log("兩只手握住"); 69 float distance = Vector3.Distance(bonesL[1].position, bonesR[1].position); 70 tran.localScale = new Vector3(distance, distance, distance); 71 } 72 73 } 74 75 void OnTriggerStay(Collider c) 76 { 77 if (isHold) 78 { 79 transform.position = bonesL[1].position - offset; 80 } 81 } 82 83 }
using Leap;using System.Collections;using System.Collections.Generic;using UnityEngine;using Leap.Unity;/// <summary>/// 旋轉/縮放/移動/// </summary>public class ControlAnimation : MonoBehaviour{
LeapProvider provider; public HandModelBase leftHandModel; public HandModelBase rightHandModel; private const float rotate_sensitive = 1500f; //旋轉靈敏度 private const float displacement_sensitive = 0.015f; //位移靈敏度 private const float rotate_initial_value = 0f; //旋轉初始位置值
/// <summary> /// 判斷條件 盡量勿動 /// </summary> const float smallestVelocity = 0.1f; const float deltaVelocity = 0.000001f; const float deltaCloseFinger = 0.06f;
void Start() { provider = FindObjectOfType<LeapProvider>() as LeapProvider; }
void Update() { Scale(); Rotation(); Position(); }
/// <summary> /// 縮小 /// </summary> public void Scale() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (isOpenFullHand(hand)) { Debug.Log("大");
//Vector3 value = transform.localScale; //value += new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); //// Debug.Log(value); //transform.localScale = value; transform.Translate(Vector3.forward * Time.deltaTime * 5); } if (isCloseHand(hand)) { //Debug.Log("小"); //Vector3 value = transform.localScale; //value -= new Vector3(value.x * 0.01f, value.y * 0.01f, value.z * 0.01f); //// Debug.Log(value);
//transform.localScale = value; } } }
/// <summary> /// 旋轉 /// </summary> public void Rotation() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft || hand.IsRight) { Vector3 value = transform.localEulerAngles; value = new Vector3(/*hand.PalmPosition.y * rotate_sensitive + rotate_initial_value*/0, hand.PalmPosition.x * rotate_sensitive + rotate_initial_value, 0); transform.localEulerAngles = value; } else { hand.PalmPosition.y = transform.localEulerAngles.x; hand.PalmPosition.x = transform.localEulerAngles.y; } } }
/// <summary> /// 位移 /// </summary> public void Position() { Frame frame = provider.CurrentFrame; foreach (Hand hand in frame.Hands) { if (hand.IsLeft || hand.IsRight) { if (isMoveLeft(hand)) { transform.localPosition = new Vector3(hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; } if (isMoveRight(hand)) { transform.localPosition = new Vector3(-hand.PalmPosition.y * displacement_sensitive, 0, 0) + transform.localPosition; } } }
}
protected bool isMoveRight(Hand hand)// 手划向右邊 { Debug.Log("左滑"); return hand.PalmVelocity.x > deltaVelocity && !isStationary(hand); }
protected bool isMoveLeft(Hand hand) // 手划向左邊 { Debug.Log("右滑"); //x軸移動的速度 deltaVelocity = 0.7f isStationary (hand) 判斷hand是否禁止 return hand.PalmVelocity.x < -deltaVelocity && !isStationary(hand); }
protected bool isStationary(Hand hand)// 固定不動的 { return hand.PalmVelocity.Magnitude < smallestVelocity; }
protected bool isCloseHand(Hand hand) //是否握拳 { Debug.Log("握拳"); List<Finger> listOfFingers = hand.Fingers; int count = 0; for (int f = 0; f < listOfFingers.Count; f++) { //循環遍歷所有的手~~ Finger finger = listOfFingers[f]; if ((finger.TipPosition - hand.PalmPosition).Magnitude < deltaCloseFinger) // Magnitude 向量的長度 。是(x*x+y*y+z*z)的平方根。 //float deltaCloseFinger = 0.05f; { count++; // if (finger.Type == Finger.FingerType.TYPE_THUMB) // Debug.Log ((finger.TipPosition - hand.PalmPosition).Magnitude); } } return (count == 5); }
protected bool isOpenFullHand(Hand hand) //手掌全展開~ { Debug.Log("展開"); //Debug.Log (hand.GrabStrength + " " + hand.PalmVelocity + " " + hand.PalmVelocity.Magnitude); return hand.GrabStrength == 0; }}