Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

By-pass the 'shortest route' aspect of Quaternion.Slerp

Discussion in 'Scripting' started by alexanderameye, Mar 5, 2017.

  1. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    736
    Hey,

    when using Quaternion.Slerp for rotating an object, the function will pick the shortest path to get to that position. Is there any way to bypass this and force the direction of the rotation (clockwise or counter-clockwise) or should I use another function?

    I need to rotate a door let's say from 0 degrees to 225 degrees. But instead of the door going through each and every one of the 225 degrees, it rotates the other way around so it only has to rotate 135 degrees, which is not what I want.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    5,921
    Well... no, Quaternion.Slerp doesn't have an override for this as what would the override be? There are infinite number of paths from A to B, how would you parameterize which path to take?

    Such definitions are a bit to complicated to make a simple parameter for.

    Instead, you just do the math required to take the path you want to take.

    For example... maybe you want to rotate around a specific axis in a specific direction.

    Your door is probably rotating around some axis (up?), and you probably want to rotate some direction (clockwise?)

    OK, I'd do an animation tween of some sort. Something like:

    Code (csharp):
    1.  
    2. IEnumerator AnimateAroundAxis(Transform trans, Vector3 axis, float changeInAngle, float duration)
    3. {
    4.     var start = trans.rotation;
    5.     float t = 0f;
    6.     while(t < duration)
    7.     {
    8.         trans.rotation = start * Quaternion.AngleAxis(axis, changeInAngle * t / duration);
    9.         yield return null;
    10.         t += Time.deltaTime;
    11.     }
    12.     trans.rotation = start * Quaternion.AngleAxis(axis, changeInAngle);
    13. }
    14.  
    Noting that AngleAxis takes an axis (up?) and a direction (sign of your changeInAngle... or you can flip your axis, 5 degrees around down is like -5 degrees around up).
     
  3. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    736
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    5,921
    I again repeat what I said before:

    Maeslezo's code is making an explicit choice on what constitutes the NOT short path (assuming the path in the opposite direction of the shortest path). Just as I do with my code (assuming around some axis by some angle).

    When one wants to bypass the 'shortest route' to instead do some other route... you need to define that route as there are infinite numbers of them! The path opposite the shortest path, the path around some axis (of which there are infinite), etc.

    My code just as definitively "bypassed" the Slerp over shortest path, in that it does spherically interpolate over a path other than the shortest.

    This isn't a matter of "can it be done", it's a matter of "describing the problem in a manner that can be logically deduced".

    Basically... your OP didn't have enough information to solve the problem.
     
    Last edited: Mar 5, 2017
  5. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    776
    You could try a Bezier rotation. subdivide the slerp into two slerps. SlerpAB goes from Angle A (0) to Angle B (112.5). SlerpBC goes from B (112.5) to C (225). Then... slerp those two slerps together to get the full Bezier rotation. it won't be completely linear (it'll slow slightly near the midpoint) but should look fine.