Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

How to check when Quaternion Slerp is `done`

Discussion in '2D' started by lolmonkeyplayer, Oct 31, 2020.

  1. lolmonkeyplayer

    lolmonkeyplayer

    Joined:
    Sep 24, 2020
    Posts:
    5
    I have a top down Game, some turrets and enemies. The turrets rotate to the enemy and the enemy follows a path and rotate (follows) the generated path line.

    I need to know when the turret completed the rotate so I can implement relevant code here

    My scripts are:

    Turrets chasing the enemies
    Code (csharp):
    1.  
    2.     private void OnTriggerStay2D(Collider2D collision)
    3.     {
    4.         if (collision.gameObject.CompareTag("Enemy"))
    5.         {
    6.             Vector3 enemyPosition = collision.transform.position;
    7.             Vector3 vectorToTarget = (enemyPosition - transform.position).normalized;
    8.             float Angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
    9.             Quaternion q = Quaternion.AngleAxis(Angle, Vector3.forward);
    10.             transform.rotation = Quaternion.Slerp(transform.rotation, q, Time.deltaTime * RotationSpeed);
    11.             inVision = true;
    12.         }
    13.     }
    14.  
    Enemies moving and rotating correctly to the generated path line:
    Code (csharp):
    1.  
    2.    Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - rb.position).normalized;
    3.    SteerTowardsTarget(direction);
    4.    Vector2 force = direction * Speed * Time.deltaTime;
    5.    rb.AddForce(force);
    6.  
    7.     void SteerTowardsTarget(Vector2 direction)
    8.     {
    9.         float targetRot = Vector2.Angle(Vector2.right, direction);
    10.         if (direction.y < 0.0f)
    11.             targetRot *= -1;
    12.         float rot = Mathf.MoveTowardsAngle(transform.localEulerAngles.z, targetRot, 1.0f);
    13.         transform.eulerAngles = new Vector3(0f, 0f, rot);
    14.     }
    15.  
     
  2. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    Well first, you're using
    Slerp
    incorrectly.
    The third parameter should not be something that represents movement over time (I.E:
    Time.deltaTime * RotationSpeed
    ), it should be a number between 0 and 1. This is the same for all other lerp-type methods.

    The third parameter represents the percentage between the two rotations, where:
    • 0 = Exactly the first rotation value.
    • 1 = Exactly the second rotation value.
    • 0.5 = The half-way point between the two rotations.
    With that in mind, you can tell when a
    Slerp
    is "done" by reading the value of the third parameter, checking if it's either 0 (for the first rotation) or 1 (for the second rotation).
    For example:
    Code (CSharp):
    1. public class Example : MonoBehaviour {
    2.    public float lerpSpeed;
    3.    private float lerpPercent = 0f;
    4.  
    5.    void Update() {
    6.       lerpPercent = Mathf.MoveTowards(lerpPercent, 1f, Time.deltaTime * lerpSpeed);
    7.  
    8.       transform.rotation = Quaternion.Slerp(/*from-rotation*/, /*to-rotation*/, lerpPercent);
    9.  
    10.       if(lerpPercent >= 1f) {
    11.          //Rotation slerp has finished. Do something else now.
    12.       }
    13.    }
    14. }
     
    tyt2008cn and lolmonkeyplayer like this.
  3. lolmonkeyplayer

    lolmonkeyplayer

    Joined:
    Sep 24, 2020
    Posts:
    5
    Solved, thank you!