分享一個功能:用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<Collider>();
}
/// <summary>
/// 抓住的事件
/// </summary>
/// <param name="e"></param>
void OnGrab(AmeliGrabEvent e)
{
lastPos = e.grabber.transform.position;//記錄手的位置
grab = true;
}
/// <summary>
/// 手抓住球拖動的事件,這個事件是在update里面實現的
/// </summary>
/// <param name="e"></param>
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;
}
/// <summary>
/// 用來控制手松開之后球的慣性
/// </summary>
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
}
}