VRTK手势匹配

 



 

 

 



被抓物体身上,都要挂如下脚本:

 



 



有时候会遇到一个Bug,就是把手中的模型删掉之后,发现手势不能回去了,僵硬不动,出现问题就是,删除的物体没有调用强制脱手的方法

GameObject hand = grapObj.GetComponent<VRTK_InteractableObject>().GetGrabbingObject();
if (hand)
{
   hand.GetComponent<VRTK_InteractGrab>().ForceRelease();
}


在测试场景中获取手势的位置和旋转值

 

 


下面是是涉及到的脚本:


InHandAnimationType.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InHandAnimationType : MonoBehaviour, IHandAnimationBaseObject
{

    [SerializeField]
    private HandAnimationType aniType;

    [SerializeField]
    private Hand_UseAnimationFingerType usingFingerButtonType = Hand_UseAnimationFingerType.None;
    public HandAnimationType type
    {
        get
        {
            return aniType;
        }
    }

    public Hand_UseAnimationFingerType usingFingerType
    {
        get
        {
            return usingFingerButtonType;
        }
    }
}

 


 VRTKExtend_LikeChildOfControllerGrabAttach.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;
using VRTK.GrabAttachMechanics;

namespace VRTK_Extend
{
    public class VRTKExtend_LikeChildOfControllerGrabAttach : VRTK_BaseGrabAttach
    {
        [Header("左手设置")]
        public Vector3 positionInLeftHand;//被抓住时 相对于左手的位置
        public Vector3 rotationInLeftHand;//被抓住时 相对于左手的旋转
        [Header("右手设置")]
        public Vector3 positionInRightHand;//被抓住时 相对于右手的位置
        public Vector3 rotationInRightHand;//被抓住时 相对于右手的旋转

        private Vector3 deltaPosition;//
        private Vector3 deltaRotation;//

        protected override void Initialise()
        {
            tracked = false;
            climbable = false;
            kinematic = true;
        }

        //控制器物体
        protected GameObject controllerObj;
        protected virtual void SetSnappedObjectPosition(GameObject obj)
        {
            controllerObj = grabbedObjectScript.GetGrabbingObject();
            if (precisionGrab)
            {
                deltaPosition = obj.transform.position - controllerObj.transform.position;
                //deltaPosition = controllerObj.transform.InverseTransformPoint(obj.transform.position);
                deltaRotation = obj.transform.rotation.eulerAngles - controllerObj.transform.rotation.eulerAngles;
                //deltaRotation = controllerObj.transform.rotation.eulerAngles - obj.transform.rotation.eulerAngles;
            }
            else
            {
                VRTK_ControllerReference controllerReference = VRTK_ControllerReference.GetControllerReference(controllerObj);
                switch (controllerReference.hand)
                {
                    case SDK_BaseController.ControllerHand.Left:
                        deltaPosition = positionInLeftHand;
                        deltaRotation = rotationInLeftHand;
                        break;
                    case SDK_BaseController.ControllerHand.Right:
                        deltaPosition = positionInRightHand;
                        deltaRotation = rotationInRightHand;
                        break;
                    case SDK_BaseController.ControllerHand.None:
                        deltaPosition = Vector3.zero; deltaRotation = Vector3.zero;
                        Debug.LogError("手柄类型未知");
                        break;
                }
            }

        }


        public override bool StartGrab(GameObject grabbingObject, GameObject givenGrabbedObject, Rigidbody givenControllerAttachPoint)
        {
            if (base.StartGrab(grabbingObject, givenGrabbedObject, givenControllerAttachPoint))
            {
                SetSnappedObjectPosition(givenGrabbedObject);
                return true;
            }
            return false;
        }
        public override void ProcessUpdate()
        {
            if (grabbedObjectScript == null)
                return;
            grabbedObjectScript.transform.position = controllerObj.transform.position + controllerObj.transform.rotation * deltaPosition;
            grabbedObjectScript.transform.rotation = controllerObj.transform.rotation * Quaternion.Euler(deltaRotation);
        }


    }
}


 AvatarHandController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;

public enum HandAnimationType
{
    Xian,tttt,ffff
}

/// <summary>
/// 控制手部使用物体动画播放的按键类型
/// </summary>
public enum Hand_UseAnimationFingerType
{
    None = -1,Thumb = 0,Index = 1,BottomThree = 3
}
/// <summary>
/// 抓取物体身上所携带的动画信息
/// </summary>
public interface IHandAnimationBaseObject
{
    HandAnimationType type {  get; }//动作的类型(播放动画的类型)
    Hand_UseAnimationFingerType usingFingerType { get; }//控制使用物体动画播放的按键
}
/// <summary>
/// 手部动画控制器
/// </summary>
public class AvatarHandController : MonoBehaviour {

    [Header("手部设置")]

    [Tooltip("控制器类型")]
    public SDK_BaseController.ControllerType controllerType;
    [Tooltip("控制器事件来源,如果没有指定会自动寻找")]
    public VRTK_ControllerEvents controllerEvents;
    [Tooltip("触碰事件来源")]
    public VRTK_InteractTouch interactTouch;
    [Tooltip("抓取事件来源")]
    public VRTK_InteractGrab interactGrab;
    [Tooltip("使用事件来源")]
    public VRTK_InteractUse interactUse;

    //控制大拇指的按键
    protected SDK_BaseController.ButtonTypes thumbAxisButton = SDK_BaseController.ButtonTypes.Touchpad;
    //控制食指的按键
    protected SDK_BaseController.ButtonTypes indexAxisButton = SDK_BaseController.ButtonTypes.Trigger;
    //控制中指的按键
    protected SDK_BaseController.ButtonTypes middleAxisButton = SDK_BaseController.ButtonTypes.MiddleFinger;
    //控制无名指的按键
    protected SDK_BaseController.ButtonTypes ringAxisButton = SDK_BaseController.ButtonTypes.RingFinger;
    //控制小拇指的按键
    protected SDK_BaseController.ButtonTypes pinkyAxisButton = SDK_BaseController.ButtonTypes.PinkyFinger;
    //控制后三个手指的按键
    protected SDK_BaseController.ButtonTypes threeFingerAxisButton = SDK_BaseController.ButtonTypes.Grip;

    [Header("手指状态设置")]
    public VRTK_ControllerEvents.AxisType thumbState = VRTK_ControllerEvents.AxisType.SenseAxis;
    public VRTK_ControllerEvents.AxisType indexState = VRTK_ControllerEvents.AxisType.Axis;
    public VRTK_ControllerEvents.AxisType middleState = VRTK_ControllerEvents.AxisType.Axis;
    public VRTK_ControllerEvents.AxisType ringState = VRTK_ControllerEvents.AxisType.Axis;
    public VRTK_ControllerEvents.AxisType pinkyState = VRTK_ControllerEvents.AxisType.Axis;
    public VRTK_ControllerEvents.AxisType threeFingerState = VRTK_ControllerEvents.AxisType.Axis;
    
    private VRTK_ControllerEvents.AxisType pointState = VRTK_ControllerEvents.AxisType.SenseAxis;
    protected VRTK_ControllerReference controllerReference;
    [Tooltip("手部动画控制器")]
    protected Animator animator;
    [Tooltip("是否根据控制器类型自动设置手指对应的按键类型")]
    public bool autoSetFingersForControllerType;


    #region 动画参数

    private const string BASELAYER = "Base Layer";
    private const string THUMBLAYER = "Thumb Layer";
    private const string POINTLAYER = "Point Layer";

    private int baseLayerIndex;
    private int thumbLayerIndex;
    private int pointLayerIndex;

    private int flexParam;
    private int pinchParam;
    private const string FLEX = "Flex";
    private const string PINCH = "Pinch";
    #endregion 动画参数
    protected virtual void OnEnable()
    {
        animator = GetComponent<Animator>();
        controllerEvents = (controllerEvents != null ? controllerEvents : GetComponentInParent<VRTK_ControllerEvents>());
        interactTouch = (interactTouch != null ? interactTouch : GetComponentInParent<VRTK_InteractTouch>());
        interactUse = (interactUse != null ? interactUse : GetComponentInParent<VRTK_InteractUse>());
        interactGrab = (interactGrab != null ? interactGrab : GetComponentInParent<VRTK_InteractGrab>());

        controllerReference = VRTK_ControllerReference.GetControllerReference(controllerEvents.gameObject);
        if (animator != null)
        {
            baseLayerIndex = animator.GetLayerIndex(BASELAYER);
            thumbLayerIndex = animator.GetLayerIndex(THUMBLAYER);
            pointLayerIndex = animator.GetLayerIndex(POINTLAYER);

            flexParam = Animator.StringToHash(FLEX);
            pinchParam = Animator.StringToHash(PINCH);
        }
    }

    protected virtual void OnDisable()
    {
        UnsubscribeEvents();
        controllerType = SDK_BaseController.ControllerType.Undefined;
    }


    protected virtual void Update()
    {
        if (controllerType == SDK_BaseController.ControllerType.Undefined)
            DetectController();
        else
            UpdateHandAnmator();
    }

   
    /// <summary>
    /// 统一注册事件
    /// </summary>
    protected virtual void SubscribeEvents()
    {
        if (controllerEvents != null)
        {
            SubscribeButtonAxisEvent(thumbAxisButton, thumbState, DoThumbAxisEvent);
            SubscribeButtonAxisEvent(indexAxisButton, indexState, DoIndexAxisEvent);
            SubscribeButtonAxisEvent(middleAxisButton,  middleState, DoMiddleAxisEvent);
            SubscribeButtonAxisEvent(ringAxisButton, ringState, DoRingAxisEvent);
            SubscribeButtonAxisEvent(pinkyAxisButton, pinkyState, DoPinkyAxisEvent);
            SubscribeButtonAxisEvent(threeFingerAxisButton, threeFingerState, DoThreeFingerAxisEvent);

            SubscribeButtonAxisEvent(indexAxisButton, pointState, DoPointAxisEvent);
        }

        if (interactTouch != null)
        {
            interactTouch.ControllerTouchInteractableObject += DoControllerTouch;
            interactTouch.ControllerUntouchInteractableObject += DoControllerUntouch;
        }

        if (interactGrab != null)
        {
            interactGrab.ControllerGrabInteractableObject += DoControllerGrab;
            interactGrab.ControllerUngrabInteractableObject += DoControllerUngrab;
        }

        if (interactUse != null)
        {
            interactUse.ControllerUseInteractableObject += DoControllerUse;
            interactUse.ControllerUnuseInteractableObject += DoControllerUnuse;
        }
    }

    /// <summary>
    /// 统一解除事件
    /// </summary>
    protected virtual void UnsubscribeEvents()
    {
        if (controllerEvents != null)
        {
            UnsubscribeButtonAxisEvent(thumbAxisButton, thumbState, DoThumbAxisEvent);
            UnsubscribeButtonAxisEvent(indexAxisButton, indexState, DoIndexAxisEvent);
            UnsubscribeButtonAxisEvent(middleAxisButton, middleState, DoMiddleAxisEvent);
            UnsubscribeButtonAxisEvent(ringAxisButton, ringState, DoRingAxisEvent);
            UnsubscribeButtonAxisEvent(pinkyAxisButton, pinkyState, DoPinkyAxisEvent);
            UnsubscribeButtonAxisEvent(threeFingerAxisButton, threeFingerState, DoThreeFingerAxisEvent);

            UnsubscribeButtonAxisEvent(indexAxisButton, pointState, DoPointAxisEvent);
        }

        if (interactTouch != null)
        {
            interactTouch.ControllerTouchInteractableObject -= DoControllerTouch;
            interactTouch.ControllerUntouchInteractableObject -= DoControllerUntouch;
        }

        if (interactGrab != null)
        {
            interactGrab.ControllerGrabInteractableObject -= DoControllerGrab;
            interactGrab.ControllerUngrabInteractableObject -= DoControllerUngrab;
        }

        if (interactUse != null)
        {
            interactUse.ControllerUseInteractableObject -= DoControllerUse;
            interactUse.ControllerUnuseInteractableObject -= DoControllerUnuse;
        }
    }

    protected virtual void SubscribeButtonAxisEvent(SDK_BaseController.ButtonTypes buttonType, VRTK_ControllerEvents.AxisType axisType, ControllerInteractionEventHandler eventHandler)
    {
        controllerEvents.SubscribeToAxisAliasEvent(buttonType, axisType, eventHandler);
    }

    protected virtual void UnsubscribeButtonAxisEvent(SDK_BaseController.ButtonTypes buttonType, VRTK_ControllerEvents.AxisType axisType, ControllerInteractionEventHandler eventHandler)
    {
        controllerEvents.UnsubscribeToAxisAliasEvent(buttonType, axisType, eventHandler);
    }

    //每个手指Axis缓存 0到4 依次代表每个手指
    protected float[] fingerAxis = new float[6];

    protected virtual void SetFingerAxisEvent(int fingerIndex, ControllerInteractionEventArgs e)
    {
        fingerAxis[fingerIndex] = e.buttonPressure;
    }
    protected virtual void DoThumbAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(0, e);
    }

    protected virtual void DoIndexAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(1, e);
        //Debug.Log("IndexAxis" + e.buttonPressure);
    }

    protected virtual void DoMiddleAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(2, e);
    }

    protected virtual void DoRingAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(3, e);
    }

    protected virtual void DoPinkyAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(4, e);
    }

    protected virtual void DoThreeFingerAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(2, e);
        SetFingerAxisEvent(3, e);
        SetFingerAxisEvent(4, e);
    }

    protected virtual void DoPointAxisEvent(object sender, ControllerInteractionEventArgs e)
    {
        SetFingerAxisEvent(5, e);
        //Debug.Log("PointAxis" + e.buttonPressure);
    }

    /// <summary>
    /// 检测控制器
    /// </summary>
    protected virtual void DetectController()
    {
        controllerType = VRTK_DeviceFinder.GetCurrentControllerType(controllerReference);
        if (controllerType != SDK_BaseController.ControllerType.Undefined)
        {
            if (autoSetFingersForControllerType)
            {
                switch (controllerType)
                {
                    case SDK_BaseController.ControllerType.SteamVR_ViveWand:
                    case SDK_BaseController.ControllerType.SteamVR_WindowsMRController:
                    case SDK_BaseController.ControllerType.WindowsMR_MotionController:
                        thumbState = VRTK_ControllerEvents.AxisType.Digital;
                        indexState = VRTK_ControllerEvents.AxisType.Axis;
                        middleState = VRTK_ControllerEvents.AxisType.Digital;
                        ringState = VRTK_ControllerEvents.AxisType.Digital;
                        pinkyState = VRTK_ControllerEvents.AxisType.Digital;
                        threeFingerState = VRTK_ControllerEvents.AxisType.Digital;
                        break;
                    case SDK_BaseController.ControllerType.Oculus_OculusTouch:
                    case SDK_BaseController.ControllerType.SteamVR_OculusTouch:
                        thumbState = VRTK_ControllerEvents.AxisType.Digital;
                        indexState = VRTK_ControllerEvents.AxisType.Axis;
                        middleState = VRTK_ControllerEvents.AxisType.Digital;
                        ringState = VRTK_ControllerEvents.AxisType.Digital;
                        pinkyState = VRTK_ControllerEvents.AxisType.Digital;
                        threeFingerState = VRTK_ControllerEvents.AxisType.Axis;
                        break;
                    case SDK_BaseController.ControllerType.SteamVR_ValveKnuckles:
                        thumbState = VRTK_ControllerEvents.AxisType.Digital;
                        indexState = VRTK_ControllerEvents.AxisType.SenseAxis;
                        middleState = VRTK_ControllerEvents.AxisType.SenseAxis;
                        ringState = VRTK_ControllerEvents.AxisType.SenseAxis;
                        pinkyState = VRTK_ControllerEvents.AxisType.SenseAxis;
                        threeFingerState = VRTK_ControllerEvents.AxisType.SenseAxis;
                        threeFingerAxisButton = SDK_BaseController.ButtonTypes.StartMenu;
                        break;
                    default:
                        thumbState = VRTK_ControllerEvents.AxisType.Digital;
                        indexState = VRTK_ControllerEvents.AxisType.Digital;
                        middleState = VRTK_ControllerEvents.AxisType.Digital;
                        ringState = VRTK_ControllerEvents.AxisType.Digital;
                        pinkyState = VRTK_ControllerEvents.AxisType.Digital;
                        threeFingerState = VRTK_ControllerEvents.AxisType.Digital;
                        break;
                }
            }
            UnsubscribeEvents();
            SubscribeEvents();
        }
    }
    /// <summary>
    /// 触碰事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerTouch(object sender, ObjectInteractEventArgs e)
    {
    }

    /// <summary>
    /// 脱离触碰事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerUntouch(object sender, ObjectInteractEventArgs e)
    {
    }

    /// <summary>
    /// 使用事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerUse(object sender, ObjectInteractEventArgs e)
    {
    }

    /// <summary>
    /// 松开使用 事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerUnuse(object sender, ObjectInteractEventArgs e)
    {
    }
    private IHandAnimationBaseObject currentHandAniObj;
    /// <summary>
    /// 抓取事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerGrab(object sender, ObjectInteractEventArgs e)
    {
        if (!e.target)
            return;
        currentHandAniObj = e.target.GetComponent<IHandAnimationBaseObject>();
        if (currentHandAniObj == null)
            return;
        animator.SetTrigger(currentHandAniObj.type.ToString());
        animator.SetLayerWeight(thumbLayerIndex, 0);
        animator.SetLayerWeight(pointLayerIndex, 0);
    }

    /// <summary>
    /// 松开抓取事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected virtual void DoControllerUngrab(object sender, ObjectInteractEventArgs e)
    {
        if (currentHandAniObj != null)
        {
            animator.SetTrigger(currentHandAniObj.type.ToString());
            animator.SetLayerWeight(thumbLayerIndex, 1 - fingerAxis[0]);
            animator.SetLayerWeight(pointLayerIndex, 1 - fingerAxis[5]);
            animator.SetFloat(flexParam, fingerAxis[3]);
            animator.SetFloat(pinchParam, fingerAxis[1]);
            currentHandAniObj = null;
        }
    }

    /// <summary>
    /// 更新动画
    /// </summary>
    protected virtual void UpdateHandAnmator()
    {
        if (currentHandAniObj == null)
        {
            animator.SetLayerWeight(thumbLayerIndex, 1 - fingerAxis[0]);
            animator.SetLayerWeight(pointLayerIndex, 1 - fingerAxis[5]);

            animator.SetFloat(flexParam, fingerAxis[3]);
            animator.SetFloat(pinchParam, fingerAxis[1]);
        }
        else 
        {
            if (currentHandAniObj.usingFingerType != Hand_UseAnimationFingerType.None)
            {
                animator.SetFloat(currentHandAniObj.type.ToString()+"Para", fingerAxis[(int)currentHandAniObj.usingFingerType]);
            }
        }
    }
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值