unity 旋转和万向锁

百度百科下:

使用动态欧拉角会出现万向锁现象;静态欧拉角不存在万向锁的问题。

一个典型的万向锁问题可以表述如下:先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;
      
    }

猜你喜欢

转载自blog.csdn.net/july_unity/article/details/79648138