VR物体交互

分享一个功能:用leap拉动一个固定位置的物体,拉动的同时使物体跟随手旋转,具体是这样的,手向上(下)运动,物体在世界坐标系中向上(下)旋转,手向右(左)运动,物体向右(左)旋转。手松开之后,物体要慢慢停下来,也就是模仿物理中的惯性。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[RequireComponent(typeof(AmeliGrabEventReceiver)), RequireComponent(typeof(SphereCollider))]
public class GrabRotate : MonoBehaviour
{
    public Camera cam;
    [Tooltip("Inertial falloff per second")]
    public float inertial = 0.99f;
    private Collider colObj;
    private Vector3 lastPos;
    private bool grab;
    private Vector3 lastAxis;
    private float lastAngle;
    public Text dbgText;
    void Start()
    {
        colObj = transform.GetComponent();
    }

    /// 
    /// 抓住的事件
    /// 
    /// 
    void OnGrab(AmeliGrabEvent e)
    {
        lastPos = e.grabber.transform.position;//记录手的位置
        grab = true;
    }
    /// 
    /// 手抓住球拖动的事件,这个事件是在update里面实现的
    /// 
    /// 
    void OnGlobalGrabDrag(AmeliGrabEvent e)
    {
        if (e.grabbed != colObj)
            return;
        Vector3 newVec = Vector3.Normalize(e.grabber.position - transform.position);//实时的记录当前手与球位置的偏移差
        Vector3 lastVec = Vector3.Normalize(lastPos - transform.position);//计算球与手初始位置的偏移差
        Quaternion drot = Quaternion.FromToRotation(lastVec, newVec);//计算两个偏移差之间的旋转的角度
        Vector3 euler = drot.eulerAngles;
        Vector3 camfor = cam.transform.forward;
        Vector3 fwd = Vector3.Cross(camfor, Vector3.up);//(0,1,0)*(0,0,1)=(1,0,0)right方向
        transform.Rotate(cam.transform.up, euler.y, Space.World);//球绕着camera的y轴旋转角度的y分量
        transform.Rotate(fwd, -euler.x, Space.World);//这里根据实际情况判断取eular的x或y分量
        lastPos = e.grabber.transform.position;//每一帧都记录手的位置,用来求两帧之间的差值
        drot.ToAngleAxis(out lastAngle, out lastAxis);//把四元数转换成绕某个轴旋转的角度
    }
    void OnRelease(AmeliGrabEvent e)
    {
        grab = false;
    }
    /// 
    /// 用来控制手松开之后球的惯性
    /// 
    void Update()
    {
        if (grab)
            return;
        if (dbgText != null)
        {
            dbgText.text = "" + lastAngle + "\n" + transform.rotation.eulerAngles;
        }
        if (lastAngle < 0.1f)
            return;

        float dra = lastAngle;
        Vector3 camfor = cam.transform.forward;
        Vector3 fwd = Vector3.Cross(camfor, Vector3.up);
        transform.Rotate(lastAxis, dra, Space.World);//球绕着返回的轴转相应的角度
        lastAngle *= (1 - Time.deltaTime) * inertial;//角度按一定的参数递减,直到角度小于0.1
    }
}


你可能感兴趣的:(VR物体交互)