Unity Quaternion verwendet häufig API-Analyse- und Rotationsinterpolationsanimationsimplementierung

1. Gemeinsame APIs von Quaternion

Quaternion.FromToRotation(Vector3 fromDirection, Vector3 toDirection)

Offizielle Analyse: Erstellt eine Drehung, die von der Richtung zur Richtung zur Richtung dreht.
Chinesische Bedeutung: Erstellt eine Drehung von der Richtung „Form“ zur Richtung „Ziel“. Stellen Sie sich
eine Szene wie diese vor. Wir verwenden die API Quaternion.FromToRotation(), um das Hauptobjekt in der Figur umzuwandeln unten Wie soll die Z-Achse (blaue Achse) von (m_MainTran) zum Zielobjekt (m_TargetTran) zeigen?
Fügen Sie hier eine Bildbeschreibung ein
der Code

            //求出目标朝向
            Vector3 targetDir = m_TargetTran.position - m_MainTran.position;
            
            //求出m_MainTran.forward旋转到目标方向需要的旋转四元数
            Quaternion  q = Quaternion.FromToRotation(m_MainTran.forward, targetDir);
            
            //把求出来的旋转四元数应用到 forward 方向
            Vector3 finalDir = q * m_MainTran.forward; 
            
            //最后让主目标的 forward 朝向计算出来的方向
            m_MainTran.forward = finalDir;

Das Parsen ist auskommentiert. Schauen Sie sich als nächstes den Effekt an.
Fügen Sie hier eine Bildbeschreibung ein
Wenn wir möchten, dass die x-Achse des Hauptziels dem Ziel zugewandt ist, ist dies die richtige Richtung. kann so geschrieben werden

            //求出目标朝向
            Vector3 targetDir = m_TargetTran.position - m_MainTran.position;

            //求出m_MainTran.right旋转到目标方向需要的旋转四元数
            Quaternion q = Quaternion.FromToRotation(m_MainTran.right,targetDir);

            //把求出来的旋转四元数应用到 right 方向
            Vector3 finalDir = q * m_MainTran.right;

            //最后让主目标的 right 朝向计算出来的方向
            m_MainTran.right = finalDir;

Renderings
Fügen Sie hier eine Bildbeschreibung ein
Dies ist in 2D-Spielen nützlich. Denn in 2D-Spielen lassen wir im Allgemeinen die x- oder y-Achse des Objekts zum Ziel zeigen, nicht die z-Achse

Quaternion.LookRotation(Vector3 vorwärts, Vector3 nach oben = Vector3.up)

  • Kanpo-Analyse: Erstellt eine Rotation mit den angegebenen Vorwärts- und Aufwärtsrichtungen
  • Chinesische Bedeutung: eine Rotation erstellen. Machen Sie die positive Richtung (z-Achse) des Zielpunkts zum Ziel nach vorne.
  • Tipp: Beim Blick auf das Ziel kann die Y-Achse über oder unter der Z-Achse liegen. Der zweite Parameter wird hier zur Steuerung verwendet. Wenn er nicht ausgefüllt ist, liegt der Standardwert über Vector.up. Wenn Sie die Richtung ändern möchten, können Sie Vector.down verwenden

In derselben Szene verwenden wir Quaternion.LookRotation(), um das Ziel in die Zielrichtung zu richten, und den obigen Code

            //求出目标方向
            Vector3 targetDir = m_TargetTran.position - m_MainTran.position;
            
            //计算出z轴朝向目标方向需要的旋转四元数
            Quaternion rotation =  Quaternion.LookRotation(targetDir,Vector3.up);
            
            //让m_MainTran.rotation等于求出的旋转
            m_MainTran.rotation = rotation;

Effektbild
Fügen Sie hier eine Bildbeschreibung ein
Es ist ersichtlich, dass das Hauptobjekt auch erfolgreich dem Ziel zugewandt ist. Die mit dieser Methode erhaltene Drehung stellt die Drehung dar, die erforderlich ist, damit die Z-Achse in die Zielrichtung zeigt. Was wäre, wenn wir möchten, dass die X-Achse in die Zielrichtung zeigt?

  • Nachdem Sie das Ergebnis ermittelt haben, können Sie Ihr Recht Ihrem Stürmer gleichsetzen. Wie zum Beispiel der folgende Code
            Vector3 targetDir = m_TargetTran.position - m_MainTran.position;
            Quaternion rotation =  Quaternion.LookRotation(targetDir,Vector3.up);
            m_MainTran.rotation = rotation;
            
            //上面的代码会使z轴朝向目标。 这里在这基础上让 right 朝向 forward 就可以了
            m_MainTran.right = m_MainTran.forward;

Darstellungen
Fügen Sie hier eine Bildbeschreibung ein

2. Realisierung von Rotationsinterpolation und Animation

Quaternion.Lerp(Quaternion a, Quaternion b, float t)

  • 官文解析:Interpoliert zwischen a und b um t und normalisiert das Ergebnis anschließend. Der Parameter t ist auf den Bereich [0, 1] beschränkt.
  • Chinesische Bedeutung: Interpolieren Sie zwischen zwei Quaternionen a und b, Interpolationsbereich t = [0 ~ 1]

Wir können Quaternion.Lerp() verwenden, um eine Rotationsanimation zu erreichen. Beachten Sie, dass die hier eingegebenen Parameter Quaternionen sind. Wir können Quaternion.FromToRotation() oder Quaternion.LookRotation() oben verwenden, um die gewünschten Parameter zu finden.

Stellen wir uns als nächstes vor, dass sich die Z-Achse des Hauptziels innerhalb von 2 Sekunden in die Zielrichtung dreht

    private bool isRotating = false;
    private float curTime = 0;
    private float AllTime = 3;

    private Quaternion oldQ;
    private Quaternion targetQ;
    
    // Update is called once per frame
    void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.A))
        {
    
    
            isRotating = true;
            curTime = 0;
            
            //当前旋转
            oldQ = m_MainTran.rotation;
            //目标旋转
            targetQ = Quaternion.LookRotation(m_TargetTran.position - m_MainTran.position);
        }

        if (isRotating)
        {
    
    
            curTime += Time.deltaTime; 
            float t = curTime / AllTime;
            t = Mathf.Clamp(t, 0, 1);
            
            //用t进行插值
            Quaternion lerpQ = Quaternion.Lerp(oldQ,targetQ,t);
            //设置到目标旋转
            m_MainTran.rotation = lerpQ;

            Debug.Log($"{
      
      GetType()} curT:{
      
      t}");
            if (t >= 1)
            {
    
    
                isRotating = false;
            }
        }
    }

Wirkungsdiagramm
Bitte fügen Sie eine Bildbeschreibung hinzu
Manchmal benötigen wir andere Achsen, z. B. die X-Achse, die dem Ziel zugewandt ist. Wie geht das? Als nächstes implementieren wir ihn, den Code

    private bool isRotating = false;
    private float curTime = 0;
    private float AllTime = 3;

    private Vector3 oldDir;
    private Quaternion oldQ;
    private Quaternion targetQ;
    
    // Update is called once per frame
    void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.A))
        {
    
    
            isRotating = true;
            curTime = 0;
            
            //记录起始点的朝向
            oldDir = m_MainTran.right;
            //起始插值参数(对于oldDir方向来说,起始不需要旋转。所以这里是Quaternion.identity)
            oldQ = Quaternion.identity;
            //目标插值参数
            targetQ = Quaternion.FromToRotation(m_MainTran.right, m_TargetTran.position - m_MainTran.position);
        }

        if (isRotating)
        {
    
    
            curTime += Time.deltaTime; 
            float t = curTime / AllTime;
            t = Mathf.Clamp(t, 0, 1);
            
            //用t进行插值
            Quaternion lerpQ = Quaternion.Lerp(oldQ,targetQ,t);
            //设置到目标旋转
            m_MainTran.right = lerpQ * oldDir;

            Debug.Log($"{
      
      GetType()} curT:{
      
      t}");
            if (t >= 1)
            {
    
    
                isRotating = false;
            }
        }
    }

Effektbild:
Bitte fügen Sie eine Bildbeschreibung hinzuDem Code werden Kommentare hinzugefügt. Drücken Sie die A-Taste. Wir können sehen, dass sich unsere X-Achse zum Ziel gedreht hat

Quaternion.Slerp(Quaternion a, Quaternion b, float t)

Dies ist eine sphärische Interpolation und der Animationseffekt ist möglicherweise besser als bei Quaternion.Lerp ().
Die spezifische Verwendung ist die gleiche wie bei Quaternion.Lerp(). Sie müssen lediglich Lerp() im obigen Code in Slerp() ändern, um den Effekt zu sehen. Sie sind hier nicht aufgeführt. Sie können es selbst ersetzen.

Quaternion.RotateTowards(Quaternion from,Quaternion to,float maxDegreesDelta)

  • Offizielle Analyse: Dreht eine Drehung von auf nach
  • Chinesische Bedeutung: Drehen Sie die Drehung von nach nach. Der Drehwinkel beträgt maxDegreesDelta, die endgültige Drehung wird jedoch nicht größer als to sein. Hier ist also der theoretische maximale Drehwinkel.

Sie können sich den Quellcode ansehen. Tatsächlich wird Quaternion.SlerpUnclamped() verwendet, um ihn am Ende zu berechnen. Ermitteln Sie zuerst den Gesamtwinkel und verwenden Sie dann
maxDegreesDelta / Gesamtwinkel als Interpolation t

    public static Quaternion RotateTowards(
      Quaternion from,
      Quaternion to,
      float maxDegreesDelta)
    {
    
    
      float num = Quaternion.Angle(from, to);
      return (double) num == 0.0 ? to : Quaternion.SlerpUnclamped(from, to, Mathf.Min(1f, maxDegreesDelta / num));
    }

Mit dieser Methode können wir den Drehwinkel angeben, um zum Ziel zu drehen. Als nächstes versuchen wir es mit dem Code

    private bool isRotating = false;
    private float perAngel = 15;//每秒转15度
    private Quaternion targetQ;
    
    // Update is called once per frame
    void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.A))
        {
    
    
            isRotating = true;
            curTime = 0;
            
            //目标插值参数
            targetQ = Quaternion.LookRotation(m_TargetTran.position - m_MainTran.position);
        }
        
        if (isRotating)
        {
    
    
            //计算出每帧的旋转
            Quaternion rotQ = Quaternion.RotateTowards(transform.rotation,targetQ,perAngel * Time.deltaTime);
            //设置到目标旋转
            m_MainTran.rotation = rotQ;
            
            if (m_MainTran.rotation.Equals(targetQ))
            {
    
    
                isRotating = false;
                Debug.Log($"{
      
      GetType()} exit rot");
            }
        }
    }

Renderings:
Bitte fügen Sie eine Bildbeschreibung hinzu

Quaternion AngleAxis(Float-Winkel, Vector3-Achse)

  • Kanpo-Analyse: Erstellt eine Drehung, die den Winkel in Grad um die Achse dreht

  • Chinesische Bedeutung: eine Rotation erstellen. Stellt die Achsenrichtung als Drehachse und den Drehwinkel dar

  • Mit dieser Methode können wir unsere Ausrichtung entlang einer beliebigen Achse um jeden Winkel drehen, genau so, wie wir es möchten.
    Beispielsweise drehen wir uns in 2D-Spielen im Allgemeinen entlang Vector.forward.
    In welcher Richtung sollten wir uns im 3D-Raum drehen?

Mit dem Kreuzprodukt können wir die Rotationsachse ermitteln . Die mathematische Bedeutung des Kreuzprodukts : Vektor c = Vektor3.Kreuz(a,b); Der berechnete Vektor c steht senkrecht auf der durch die Vektoren a und b gebildeten Ebene. Dieser Vektor c ist die gewünschte Rotationsachse.

Als nächstes verwenden wir Quaternion.AngleAxis(), um die vorherige Rotationsanimation zu implementieren. oberer Code

    private bool isRotating = false;
    private float perAngel = 15;//每秒转15度
    private Vector3 rotAxis;
    
    // Update is called once per frame
    void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.A))
        {
    
    
            isRotating = true;

            //求出旋转轴
            rotAxis = Vector3.Cross(m_MainTran.forward,m_TargetTran.position - m_MainTran.position);
        }
        
        if (isRotating)
        {
    
    
            //计算出每帧的旋转
            Quaternion rotQ = Quaternion.AngleAxis(perAngel * Time.deltaTime,rotAxis);
            //应用旋转
            m_MainTran.forward = rotQ * m_MainTran.forward;
            
            //如果旋转到只差2度,就旋转到目标方向,并退出旋转动画
            if (Vector3.Angle(m_MainTran.forward,m_TargetTran.position - m_MainTran.position) <= 2)
            {
    
    
                m_MainTran.forward = m_TargetTran.position - m_MainTran.position;
                isRotating = false;
                Debug.Log($"{
      
      GetType()} exit rot");
            }
        }
    }

Effektbild:
Bitte fügen Sie eine Bildbeschreibung hinzu
Es ist zu erkennen, dass sich das Hauptobjekt erfolgreich dem Ziel zugewandt hat.

3. Fazit

  • Quaternion ist ein relativ abstraktes Konzept, aber wenn Sie die obige API beherrschen, können Sie es beliebig umdrehen~

Ich denke du magst

Origin blog.csdn.net/aaa27987/article/details/123093866
Empfohlen
Rangfolge