This site uses strictly necessary cookies. More Information

X- Home /

# Not interpolate quaternion on shortest path?

Hi,

I have been searching a long time but I did not find something that hints at a solution. Basically I want to smoothly interpolate between two Rotations. However I do not want to interpolate along the shortest path.

When I use Quaternion.Lerp, SLerp or RoateTowards it would rotate 90 degrees when interpolating between (in eulers) (0,270,0) and (0,0,0), but I want it to rotate 270 degrees.

I tried using eulerAngles on both source and target rotation, interpolating the vectors and reconverting them into quaternions with Quaternion.Euler but that gives me the same results.

Is there an inbuilt way to use this "non-optimal" interpolation?

greetings

I was just about to write that this does not work either, since I already tried it, but it got me thinking.

$$anonymous$$y problem originated from the fact that rotation.eulerAngles is clamped between 0 and 360 and that is why I was interpreting the interpolation wrong.

I found that localEulerAngles contains the rotation displayed in the editor, so I can work with that.

Thank you for your time

Edit: how do I check a question answered? Does convert to answer do this, or does this only convert my comment?

**Answer** by robertbu
·
Jun 21, 2013 at 02:53 PM

If you do some searching around on UA, you will find a number of answers to this question. One answer is to treat eulerAngles as write-only and maintain your own Vector3. Here is one of those answers:

http://answers.unity3d.com/questions/475760/rotation-direction-in-coroutine.html

@FreetimeCoder - eulerAngles has a habit of changing representation on you. You can get around the 0/360 boundary by changing the representation in the Vector3 you maintain.

Ok, but is there a reason not to use localEulerAngles? From what I can tell it does exactly what I need.

@FreetimeCoder - As explained in the answer at the link provided, eulerAngles can change its representation. Write a bit of code that sets the eulerAngles to (180,0,0), and then use a Debug.Log() statement to read it back. You will get (0,180,180). eulerAngles changes in a predictable pattern, so if you are careful, it may work for you. But as stated, it is safer to keep your own Vector3 and never read eulerAngles.

I see what you mean, however I cannot use that method because the first time I get a rotation is when the level started and I read localEulerAngles from the gameobject's transformation. I never modify it afterwards only interpolate something else between different objects' transformations.

Ok, I found that transform.localRotation is much better than localEulerAngles, because the later sometimes even changes between in-editor and in-game while the localRotation Quaternion does not.

(I must confess this again takes me back to the "shortest path" thing, but I have given up on trying to acheive a perfect solution)

I think this solves this topic.

**Answer** by Maeslezo
·
Jan 27, 2017 at 09:14 AM

I had the same problem, so I have written the lerp and slerp myself, with a flag to indicate whether you want to force the short way or not. I am pretty sure that Unity checks that to invert the rotation. With this code, you can indicate if you want that behaviour.

I have checked myself and it seems it works ok, but check yourself just in case:

```
public static class QuaternionExtension
{
public static Quaternion Lerp(Quaternion p, Quaternion q, float t, bool shortWay)
{
if (shortWay)
{
float dot = Quaternion.Dot(p, q);
if (dot < 0.0f)
return Lerp(ScalarMultiply(p, -1.0f), q, t, true);
}
Quaternion r = Quaternion.identity;
r.x = p.x * (1f - t) + q.x * (t);
r.y = p.y * (1f - t) + q.y * (t);
r.z = p.z * (1f - t) + q.z * (t);
r.w = p.w * (1f - t) + q.w * (t);
return r;
}
public static Quaternion Slerp(Quaternion p, Quaternion q, float t, bool shortWay)
{
float dot = Quaternion.Dot(p, q);
if (shortWay)
{
if (dot < 0.0f)
return Slerp(ScalarMultiply(p, -1.0f), q, t, true);
}
float angle = Mathf.Acos(dot);
Quaternion first = ScalarMultiply(p, Mathf.Sin((1f - t) * angle));
Quaternion second = ScalarMultiply(q, Mathf.Sin((t) * angle));
float division = 1f / Mathf.Sin(angle);
return ScalarMultiply(Add(first, second), division);
}
public static Quaternion ScalarMultiply(Quaternion input, float scalar)
{
return new Quaternion(input.x * scalar, input.y * scalar, input.z * scalar, input.w * scalar);
}
public static Quaternion Add(Quaternion p, Quaternion q)
{
return new Quaternion(p.x + q.x, p.y + q.y, p.z + q.z, p.w + q.w);
}
}
```

An implementation that's a bit more optimised would be:

```
public static Quaternion Slerp(Quaternion p, Quaternion q, float t, bool shortWay)
{
float dot = Quaternion.Dot(p, q);
float sign = (shortWay && dot < 0.0f) ?-1f : 1f;
float angle = Mathf.Acos(dot * sign);
float division = 1f / Mathf.Sin(angle);
float t0 = Mathf.Sin((1f - t) * angle) * division * sign;
float t1 = Mathf.Sin((t) * angle) * division;
return new Quaternion(
p.x*t0 + q.x * t1,
p.y*t0 + q.y * t1,
p.z*t0 + q.z * t1,
p.w*t0 + q.w * t1
);
}
```

Note that I currently can't test this method as I don't have Unity at hand. I can also not guarantee that it works as I haven't verified the original method, but it looks right. My version is just a simplification / inlining of the original post. It reduces the method calls and also the required multiplications

Imagine if Unity made it easy for us and added this solution and all you'd have to do is to set an additional bool param, wouldn't that be awesome ... I've had to look up this issue so many times over the years and always ended up implementing some length workaround.

**Answer** by wolfgraphicsLLC
·
Jan 28 at 07:06 PM

ok @FreetimeCoder i know of at least 2 ways to fix that off the top of my head first as a dev not as a just programmer how is your object set up wat does the scenario look like in the scene view and as well the inspector setting s and setup in hierarchy cold you either upload a sort video or a couple screen shots showing this? or another option is you could go to discord to https://discord.gg/gjWDxcPC and go to the programing and general unity channel and @ john nic?9wolfgraphicsllc) that's me I am one of the tutors and moderators there as well there is a create a ticket channel where you can get a little more focused assistance. and i would be glad to look it over and walk you through and trouble shoot it with you for like i always say when it comes to dev work and coding alike there is always more than one way to skinn a cat

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.

### Follow this Question

### Related Questions

Tilt aircraft based on accelerometer 0 Answers

Drawing a path - rotation of corner textures 1 Answer

How can I collect the positions of my waypoint objects which mark out a path or route? 2 Answers

Push an object along a path? 2 Answers

How to show the objects movements by line or texture? 2 Answers