百度百科下:
使用动态欧拉角会出现万向锁现象;静态欧拉角不存在万向锁的问题。
一个典型的万向锁问题可以表述如下:先heading45°再pitch90°,这与先pitch90°再bank45°是等价的。事实上,一旦选择±90°作为pitch角,就会导致第一次旋转和第三次旋转等价,整个旋转表示系统被限制在只能绕竖直轴旋转,丢失了一个表示维度。这种角度为±90°的第二次旋转使得第一次和第三次旋转的旋转轴相同的现象,称作万向锁。
死锁的原因是,xyz 的选转,必须要存在轴的父子关系,才能选转
这种关系的存在,必然就会导致当俩个轴重合时,出现选转卡死
所以使用四元素,矩阵解决旋转问题--ratation 是四元数单是为了方便显示为 欧拉角,xyz 形式
代码测试:
using UnityEngine;
using System.Collections;
public class RotateSample : MonoBehaviour
{
public GameObject prefab_ST;
public GameObject prefab_STParent ;
public float RotateSpeed = 3;
void Start() {
SetPrefab();
}
public void SetPrefab()
{
prefab_ST.transform.SetParent(leftHand.transform);
prefab_ST.transform.localPosition = new Vector3(0, 0.1f, 0.12F);
prefab_ST.transform.localEulerAngles = Vector3.zero;
}
bool isfont = false;
bool isce = false;
bool isfushi = false;
bool isbace = false;
void Update() {
if (isfont) {
//prefab_ST.transform.localEulerAngles 进行赋值旋转时会,万象角死锁 ----导致物体晃动,或不停旋转 。故旋转都转化为四元素在进行插值运算;(代码 四个都以prefab_ST.transform.localEulerAngles 方式旋转时会出现死锁)
// prefab_ST.transform.localEulerAngles = Vector3.Lerp (prefab_ST.transform.localEulerAngles, new Vector3(0, 0, 0),Time.deltaTime* RotateSpeed);
// float a= Vector3.Distance(prefab_ST.transform.localEulerAngles, new Vector3(0, 0, 0));
prefab_ST.transform.localRotation = Quaternion.Lerp(prefab_ST.transform.localRotation, Quaternion.Euler(new Vector3(0, 0, 0)), Time.deltaTime * RotateSpeed);
float a = Vector3.Distance(Quaternion.ToEulerAngles(prefab_ST.transform.localRotation), new Vector3(0, 0, 0));
if ( a<0.1f){
isfont = false;
}
}
if (isce)
{
prefab_ST.transform.localRotation = Quaternion.Lerp(prefab_ST.transform.localRotation, Quaternion.Euler(new Vector3(0, 270, 0)), Time.deltaTime * RotateSpeed);
float b = Vector3.Distance(Quaternion.ToEulerAngles(prefab_ST.transform.localRotation), new Vector3(0, 270, 0));
if (b < 0.1f)
{
isce= false;
}
}
if (isfushi)
{
prefab_ST.transform.localRotation= Quaternion.Lerp(prefab_ST.transform.localRotation, Quaternion.Euler(new Vector3(270, 0, 0)), Time.deltaTime * RotateSpeed);
float c= Vector3.Distance(Quaternion.ToEulerAngles(prefab_ST.transform.localRotation), new Vector3(270, 0, 0));
if (c < 0.2f)
{
isfushi = false;
}
}
if (isbace)
{
prefab_ST.transform.localRotation = Quaternion.Lerp(prefab_ST.transform.localRotation, Quaternion.Euler(new Vector3(0, 180, 0)), Time.deltaTime * RotateSpeed);
float d = Vector3.Distance(Quaternion.ToEulerAngles(prefab_ST.transform.localRotation), new Vector3(0, 180, 0));
if (d< 0.1f)
{
isbace = false;
}
}
}
public void font()
{
isfont = true;
isce = false;
isfushi = false;
isbace = false;
}
public void ce()
{
isce = true;
isfont = false;
isfushi = false;
isbace = false;
}
public void fushi()
{
isfushi = true;
isce = false;
isfont = false;
isbace = false;
}
public void back()
{
isbace = true;
isfushi = false;
isce = false;
isfont = false;
}