Unity通过旋转手势控制转盘旋转

在VR虚拟场景的物理实验室模块中,我想做一个切割磁感线发电机的模拟装置;为了让用户更加真实的操作设备,让用户通过手柄的旋转手势,实现转盘的同步转动。


(之后补gif图)

原理,获取到需要转动的物体中心的位置,记录鼠标按下的瞬间的位置,按下后计算每帧的鼠标移动的位置,通过这三个位置,计算角度,(即鼠标按下时与物体中心的连线 和 每一帧鼠标位置与物体中心的连线的夹角)。

通过四元数判断旋转的方向的,通过 transform.localEluerAngles方法,控制物体旋转。


modelPos = ca.WorldToScreenPoint(target1.transform.position);

坐标系转换,从世界坐标系到屏幕位置转换(屏幕位置以像素定义,左下为0,0;z的位置是以世界坐标系衡量的到相机的距离)。括号里加三维向量。

详见Unity3D中Camera类的方法。


static function Angle (from : Vector3, to : Vector3) : float
RotateAngle = Vector3.Angle (preMousePos - modelPos, mousePos - modelPos);

由from和to两者返回一个角度;即,他们的夹角。初始鼠标位置与中心,当前鼠标位置与中心的夹角。


q = Quaternion.FromToRotation (preMousePos - modelPos,mousePos - modelPos);
float k = q.z > 0 ? 1 : -1;

四元数,根据q的z值,判断旋转方向是顺时针还是逆时针。z为正逆时针,为负顺时针。

大于0返回1小于0返回-1。条件运算符?:


target1.transform.localEulerAngles = localEluer;

localEulerAngles,自身欧拉角,用于读取和设置角度。等号右边是三维向量。

即transform.localEulerAngles = new Vector3(0,0,0);物体的旋转方向是默认方向。

transform.localEulerAngles = new Vector3(90,0,0);沿x轴指向,逆时针旋转90度。

transform.localEulerAngles = new Vector3(0,90,0);沿y轴指向,逆时针旋转90度。

如果将上述角度改成负数,沿着改变轴的方向,变为顺时针。


angle = localEluer.z = Mathf.Clamp (localEluer.z,-36000,36000);
static function Clamp (value : float, min : float, max : float) : float

Mathf.Clamp限制。限制value的值在min和max之间,以满足某些功能的需要。如果value小于min,返回min;如果value大于max,返回max,否则返回value。

//圣典案例
// Set the position of the transform to be that of the time
// but never less than 1 or more than 3
//随着时间设置变换位置
//但是不会小于1或大于3
function Update () {
	transform.position = Vector3(Mathf.Clamp(Time.time, 1.0, 3.0), 0, 0);
}

参数可以为float也可以为int。

源码

public Camera ca;

	private Quaternion q;

	private Vector3 mousePos;
	private Vector3 preMousePos;
	private Vector3 modelPos;

	private Vector3 localEluer;

	private bool IsSelect = false;
	private float RotateAngle;

	private float angle;

	public Transform target1;

	// Use this for initialization
	void Start () {
		modelPos = ca.WorldToScreenPoint(target1.transform.position);
		angle = localEluer.z;
		target1.transform.localEulerAngles = localEluer;
	}
	
	// Update is called once per frame
	void Update () {

		if(Input.GetMouseButtonDown (0)){
			IsSelect = true;
			preMousePos = mousePos = Input.mousePosition;
		}
		if (Input.GetMouseButton (0) && IsSelect) {
			IsSelect = true;
			mousePos = Input.mousePosition;
			RotateAngle = Vector3.Angle (preMousePos - modelPos, mousePos - modelPos);
			//print (RotateAngle);

			if (RotateAngle == 0) {
				preMousePos = mousePos;
			}
			else {
				q = Quaternion.FromToRotation (preMousePos - modelPos,mousePos - modelPos);
				float k = q.z > 0 ? 1 : -1;
				localEluer.z += k * RotateAngle;

				Debug.Log (localEluer.x);

				angle = localEluer.z = Mathf.Clamp (localEluer.z,-36000,36000);

				target1.transform.localEulerAngles = localEluer;
				preMousePos = mousePos;
			}

		}
		if(Input.GetMouseButtonUp(0)){
			IsSelect = false;
		}
	}




猜你喜欢

转载自blog.csdn.net/qq_34272906/article/details/79903312
今日推荐