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. Dismiss Notice

Help with Vector3.Lerp/Slerp for eulerAngles?

Discussion in 'Scripting' started by d34thst4lker, Sep 11, 2014.

  1. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    I'm trying to have an object Lerp/Slerp from one Vector3 point to another but for some reason the Lerping is not exactly going to the second Vectors position. If this isnt the best way to do something like this? Then what would be?

    I tried doing a Quaternion with transform.rotation but that doesnt seem to do what I am looking for.

    The above method of Vectors rotates in the way I like, I'm just not seeing the results I am looking for.

    Thank you.
     
  2. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    //JS
    function LerpTimed(firstVector : Vector3, secondVector : Vector3, time : float, totalTime : float)
    {
    return Vector3.Lerp(firstVector, secondVector, time / totalTime);
    }

    //C#
    public Vector3 LerpTimed(Vector3 firstVector, Vector3 secondVector, float time, float totalTime)
    {
    return Vector3.Lerp(firstVector, secondVector, time / totalTime);
    }

    These lerp between two vectors based on an amount of time, so if time is in seconds, and you have a totalTime from the first vector to the second, that's what it'll go to.

    I'm not sure if this is what you wanted, your problem wasn't very clear. Hope this helps.

    ~
    Another walk in the park.
     
    Last edited: Sep 11, 2014
  3. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    Thanks, sorry thats not it. I've been doing that but the values I'm expecting are not the values that are being shown.
     
  4. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Could you explain what exactly you are trying to achieve. Do you want to move from A to B? Do you want to go from one rotation to another? Do you want both?
     
  5. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    I want both, but I already have the translation working properly. I am trying to get one rotation to another. So if I'm currently at Rotation : 270, 0, 0 then I would like to get to Rotation : 225, 0, 0 ... But When I try Lerping to that Rotation, it ends up with like Rotation : 315, 180, 180

    Doesn't even make any sense
     
  6. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    Euler angles in are only a conversion from the actual Quaternion rotation objects internally have in Unity.
    You will never be able to control the euler angles of an objects rotation yourself, not unless you store the euler rotation yourself.
    Long story short, if you want to interpolate between two transform rotations, use Quaternion.Slerp.
    Take a look at the Quaternion video.
    http://unity3d.com/learn/tutorials/modules/intermediate/scripting/quaternions
     
  7. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    pseudo code:

    Vector3 curRot = transform.rotation.eulerAngles;
    curRot = Vector3.Lerp(curRot, targetRot, time);
    transform.rotation = Quaternion.Euler(curRot);

    does this help?

    ~
    Another walk in the park.
     
  8. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Show your code!
     
  9. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    I'll check the Quaternion video out but I have already tried using Quaternions and couldn't get it working. I was thinking of posting my code but got to figure out which code to include.

    Thanks for the replies
     
  10. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    That sounds like you should refactor your code first :)
     
  11. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    EDIT: You're lerping on one dimension, so a normal Vector lerp should work just fine. I think you will need to show the lerp code before we can help you! There may be no need to mess with Quaternions yet.

    ====

    ORIGINAL POST: When working with angles/rotations, it is best to convert everything to Quaternions.
    Code (csharp):
    1. void Start()
    2. {
    3.   Quaternion originalRotation = transform.rotation
    4.   Quaternion targetRotation = Quaternion.Euler(yourTargetEulerAngles);
    5. }
    6.  
    7. void Update()
    8. {
    9.   float t = percentComplete;
    10.   transform.rotation = Quaternion.Lerp(originalRotation, targetRotation, t);
    11. }
    There is also RotateTowards.
    Code (csharp):
    1. transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, speedInDegrees * Time.deltaTime);
    Rotating around x then rotating around y gives different results than rotating around y then rotating around x. This is a source of gimbal lock and the reason why euler angles can be deceptive to work with.
     
    Last edited: Sep 12, 2014
    Ghosthowl and d34thst4lker like this.
  12. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    Hmm actually that code might work. I'll give it a try next. That seems like it may do the trick!
     
  13. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    @Garth Smith ... Unfortunately that code worked just as my code originally worked... So that's not good. But thanks anyways
     
  14. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    So I figured something out.

    A rotation of (225, 0, 0) is the same thing as a rotation of (315, 180, 180). So you are lerping to the correct rotation.

    I'm guessing that means your rotation is around the wrong axis. I would like to ask for two things.
    1. How is the rotation different from what you expect? How does it act now? What should it act like?
    2. Can you provide the code you are using to rotate?
     
  15. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    Well yes, that first statement is correct. It is working, but I am trying to check the current rotation with the rotation that I want to Lerp until if they are equal and then let the game now when that happens.
    But because (225,0,0) rotates to (315,180,180) the current rotation will never equal (225,0,0) and then never send the signal.

    There's no point to post my code because its just the few lines that keep getting passed around on this thread. But what I said above in this reply should allow a better understanding.

    Thank you
     
  16. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    How about checking if the angle between them is almost 0?
    Code (csharp):
    1.  
    2. if (Quaternion.Angle(originalRotation, targetRotation) < 0.01f) Debug.Log("Close enough!");
    3.  
     
  17. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    bool rotationAchieved = Vector3.Dot(curRot.eulerAngles.normalized, lerpRot.eulerAngles.normalized) == 1.0f;
    Dot product of two vectors will be 1.0f if they're the same, or -1.0f if they're completely opposite direction of each other, 0.0f if they are perpendicular(90 degrees of eachother).
     
  18. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    Emma, I don't think that comparing the Euler angles that way is reliable, because the same rotation might convert to quite different Euler angles. Using Quaternion.Angle as Thermal suggested seems like a safer bet to me.

    (But I'd be happy to be wrong on this one, and learn something new!)
     
  19. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    @JoeStrout @TwixEmma The euler angles actually come out the same. The y and z components are off by about 0.00001. The problem is coming from expecting two floats to perfectly equal each other.

    @d34thst4lker You should never compare 2 floats directly. Instead, you need to compare if two floats are close enough together. The reason for this is because floats use a base 2 numbering system, and so most numbers cannot be represented exactly in a float. Example: A float can never have the value 0.1 exactly. You can try some numbers at this site and see *almost none of them* are exact in a float.
    http://www.h-schmidt.net/FloatConverter/IEEE754.html

    This means you should do something similar to @ThermalFusion. Figure out what error is acceptable and check against that error.
     
    Last edited: Sep 15, 2014
  20. d34thst4lker

    d34thst4lker

    Joined:
    Aug 4, 2013
    Posts:
    124
    Yea sounds good! Will try that soon
    Thanks!
     
  21. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    I thought on the fly, forgot about Quaternion.Angle.
     
  22. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    With my method you could still compare within a margin of error, just change 1.0f to something like 0.99f.
    And my method WOULD work if the x, y, z values of each euler was repeated 360 degrees. Except for in some cases. I realise after posting it, that it would fail. When I saw Quaternion.Angle. But I didn't feel the need to repost or w/e since the better solution was given.
     
  23. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    @TwixEmma @JoeStrout Measuring the dot product of the quaternion's euler angles, or the angle directly should both work, because Unity will give the same eulerAngles for the quaternions. In fact, I'd be surprised if calculating an angle does not use the dot product. The key is allowing for an error.

    However, comparing the euler angles without converting to a quaternion first will cause an error since (315, 180, 180) is not anywhere close to (225, 0, 0).

    EDIT: So I decided that comparing the angle between two quaternions is better than comparing euler angles because of cases like (315, 180, 180) being the same rotation as (225, 0, 0).

    @JoeStrout I'm fairly sure that Quaternion.eulerAngles will always convert to a rotation in x, y, z order, with values between [0, 360). That is 0 through just below 360. I've tested a few rotations by inputting different but equivalent euler angles, they have always come up the same after converting to a Quaternion first. However, I'm not convinved Quaternion will always give the same euler angles, hence the EDIT above.

    EDIT: TwixEmma beat me to it!

    EDIT #2: I see there is Quaternion.Dot() so yeah I'm cool with dot products again, as long as we're not dotting euler angles!
     
    Last edited: Sep 16, 2014
  24. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    @d34thst4lker I just want to say that if you showed us your code in the first place, we might have seen the error was comparing floats and not the rotation and been able to point out the error that much sooner. There's a reason we ask to see code! =)
     
    Last edited: Sep 15, 2014
    d34thst4lker likes this.