在unity中獲取手的位置
創建一個空物體,命名為KinectManager,給該物體綁定上KinectManager 和 InteractionManager腳本
其中InteractionManager腳本上有三個紋理,Grip Hand Texture 是握拳,Release Hand Texture是手攤開的狀態,Normal Hand Texture理論上應該是手呈半握狀態並且其中的個別手指攤開,但是我從沒有觸發過
再新建一個空物體,命名為InteractionListener,新建一個腳本MyInteractionListener,這個腳本需要跟攝像機和InteractionManager相關聯,但是InteractionManager可以用kinect的屬性獲取,所以只需要將攝像機拖拽到腳本上關聯即可
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MyInteractionListener : MonoBehaviour ,InteractionListenerInterface{ [Tooltip("Camera used for screen ray-casting. This is usually the main camera. 用於屏幕光線投射的照相機。這通常是主相機。")] public Camera screenCamera; //[Tooltip("Interaction manager instance, used to detect hand interactions. If left empty, it will be the first interaction manager found in the scene.")] [Tooltip("交互管理器實例,用於檢測手交互。如果為空,它將是場景中發現的第一個交互管理器")] public InteractionManager interactionManager; // hand interaction variables 手的交互變量 private InteractionManager.HandEventType lastHandEvent = InteractionManager.HandEventType.None; // normalized and pixel position of the cursor 鼠標光標的統一化和位置 private Vector3 screenNormalPos = Vector3.zero; private Vector3 screenPixelPos = Vector3.zero; private Vector3 newObjectPos = Vector3.zero; /*[Tooltip("Minimum Z-position of the dragged object, when moving forward and back.")] public float minZ = 0f; [Tooltip("Maximum Z-position of the dragged object, when moving forward and back.")] public float maxZ = 5f;*/ /// <summary> /// UDP客戶端 /// </summary> public UDPClient udpClient; // Use this for initialization void Start () { //默認情況下,將主相機設置為屏幕攝像機 if (screenCamera == null) { screenCamera = Camera.main; } // 獲取交互管理器實例 if (interactionManager == null) { interactionManager = InteractionManager.Instance; } } // Update is called once per frame void Update () { //如果交互管理器不為空,並且已經初始化 if (interactionManager != null && interactionManager.IsInteractionInited()) { // check if there is an underlying object to be selected 檢查是否存在要選擇的基礎對象 if (lastHandEvent == InteractionManager.HandEventType.Grip && screenNormalPos != Vector3.zero) { // convert the normalized screen pos to pixel pos 將標准化屏幕POS轉換為像素POS screenNormalPos = interactionManager.IsLeftHandPrimary() ? interactionManager.GetLeftHandScreenPos() : interactionManager.GetRightHandScreenPos(); screenPixelPos.x = (int)(screenNormalPos.x * (screenCamera ? screenCamera.pixelWidth : Screen.width)); screenPixelPos.y = (int)(screenNormalPos.y * (screenCamera ? screenCamera.pixelHeight : Screen.height)); Ray ray = screenCamera ? screenCamera.ScreenPointToRay(screenPixelPos) : new Ray(); // check if there is an underlying objects 檢查是否存在底層對象 RaycastHit hit; Debug.Log("握拳"); Debug.Log(screenPixelPos); //udpClient.SocketSend(screenPixelPos.x + "," + screenPixelPos.y); //udpClient.SocketSend(screenNormalPos.x + "," + screenNormalPos.y); //udpClient.SocketSend(screenNormalPos.x.ToString("f2") + "," + screenNormalPos.y.ToString("f2"));//f2保留兩位小數 //udpClient.SocketSend("anXia"); if (Physics.Raycast(ray, out hit)) { Debug.Log("位置"); Debug.Log(hit.point); /*foreach (GameObject obj in draggableObjects) { if (hit.collider.gameObject == obj) { // an object was hit by the ray. select it and start drgging draggedObject = obj; draggedObjectOffset = hit.point - draggedObject.transform.position; draggedObjectOffset.z = 0; // don't change z-pos draggedNormalZ = (minZ + screenNormalPos.z * (maxZ - minZ)) - draggedObject.transform.position.z; // start from the initial hand-z // set selection material draggedObjectMaterial = draggedObject.GetComponent<Renderer>().material; draggedObject.GetComponent<Renderer>().material = selectedObjectMaterial; // stop using gravity while dragging object draggedObject.GetComponent<Rigidbody>().useGravity = false; break; } }*/ } } else { // continue dragging the object 繼續拖動對象 screenNormalPos = interactionManager.IsLeftHandPrimary() ? interactionManager.GetLeftHandScreenPos() : interactionManager.GetRightHandScreenPos(); // convert the normalized screen pos to 3D-world pos 將標准化的屏幕POS轉換為3D世界POS screenPixelPos.x = (int)(screenNormalPos.x * (screenCamera ? screenCamera.pixelWidth : Screen.width)); screenPixelPos.y = (int)(screenNormalPos.y * (screenCamera ? screenCamera.pixelHeight : Screen.height)); /*//screenPixelPos.z = screenNormalPos.z + draggedObjectDepth; screenPixelPos.z = (minZ + screenNormalPos.z * (maxZ - minZ)) - draggedNormalZ - (screenCamera ? screenCamera.transform.position.z : 0f);*/ //Debug.Log("手掌"); //Debug.Log(screenPixelPos); //udpClient.SocketSend(screenPixelPos.x + "," + screenPixelPos.y); //udpClient.SocketSend(screenNormalPos.x + "," + screenNormalPos.y); //udpClient.SocketSend(screenNormalPos.x.ToString("f2") + "," + screenNormalPos.y.ToString("f2")); //udpClient.SocketSend("taiQi"); //newObjectPos = screenCamera.ScreenToWorldPoint(screenPixelPos) - draggedObjectOffset; // check if the object (hand grip) was released /*bool isReleased = lastHandEvent == InteractionManager.HandEventType.Release; if (isReleased) { // restore the object's material and stop dragging the object draggedObject.GetComponent<Renderer>().material = draggedObjectMaterial; if (useGravity) { // add gravity to the object draggedObject.GetComponent<Rigidbody>().useGravity = true; } draggedObject = null; }*/ } } } public void HandGripDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos) { if (!isHandInteracting || !interactionManager) return; if (userId != interactionManager.GetUserID()) return; lastHandEvent = InteractionManager.HandEventType.Grip; //isLeftHandDrag = !isRightHand; screenNormalPos = handScreenPos; } public void HandReleaseDetected(long userId, int userIndex, bool isRightHand, bool isHandInteracting, Vector3 handScreenPos) { if (!isHandInteracting || !interactionManager) return; if (userId != interactionManager.GetUserID()) return; lastHandEvent = InteractionManager.HandEventType.Release; //isLeftHandDrag = !isRightHand; screenNormalPos = handScreenPos; } public bool HandClickDetected(long userId, int userIndex, bool isRightHand, Vector3 handScreenPos) { return true; } }
需要注意的是,獲取到的手的坐標是屏幕坐標,就是0---1的范圍,如果想要應用,還需要轉換成世界坐標,另外注意unity中的坐標軸,跟其他程序或軟件的坐標軸可能會不同
