在做项目时,很多时候可能需要做旋转功能,这个很简单,直接使用Rotate方法即可,如果在加上一个限制旋转角度,可不是简单的判断下角度就可以了。在Unity中,角度在它内部是用四元数表示的,这个我也弄不清楚,所以,在面板展示和你实际打印出来的localEulerAngles不一样!!可能你只是想改变x的角度,但是你转着转着可能看到变成x,y,z三个值都变了。
之前在网上看到一个解决方案,说是拿取localEulerAngles之后,对角度做一个变化:
float CheckAngle(float value){
float angle = value - 180;
if (angle > 0){
return angle - 180;
}
return angle + 180;
}
这个虽然可以解决部分问题,但是我这里还是遇到了一个很奇特的问题,有时候突然变成反向的了。
我自己加了一个方法:
float angle = 0;
Vector3 axis = Vector3.left;
rotateXAnim.localRotation.ToAngleAxis(out angle, out axis);
这个可以得到某一个轴的角度,然后在根据axis的方向,就能得到实际的角度
angle = CheckAngle(angle*axis.x);
if (angle > 90){
angle = 90;
rotateXAnim.localEulerAngles = new Vector3(angle, 0, 0);
}else if (angle < -90){
angle = -90;
rotateXAnim.localEulerAngles = new Vector3(angle, 0, 0);
}
结合起来,也能解决大部分问题。
可是,今天又出现一个奇怪问题,就是我前面说的,突然变成反向的角度,而且只有第一次出现,之后旋转都是正常的。
思来想去,最后想到一个曲线解决方案:
我们在初始化物体时,是知道物体的旋转角度的,那么我们就可以存储一个临时的欧拉角度,在需要旋转角度时,直接用这个临时的欧拉角度进行计算,计算得到结果之后,直接先判断角度是否超过我们给定的值,这样就不用经过四元数那一层计算了,那么也就不会出现万向锁和我上面说的问题了。
void MapRotating(Vector3 tempPosition){
Vector3 tempAngle = Vector3.zero;
tempAngle.x = tempPosition.y * 15f / scaleTrans.localScale.x;
tempAngle.y = -tempPosition.x * 15f / scaleTrans.localScale.x;
nowRotate += tempAngle;
nowRotate.x = ClampAngle(nowRotate.x, -90, 90);
SetNowRotValue(nowRotate.x, nowRotate.y, true);
}
static float ClampAngle(float angle, float min, float max) {
if (angle < -360){
angle += 360;
}
if (angle > 360){
angle -= 360;
}
return Mathf.Clamp(angle, min, max);
}
哈哈,想问题真的进入到一个思维死角里面去了,反而忘记后面这个最简单的方式了-