# Handling rotation interpolation at 180 degrees

I currently have a scene where 3d a gents move throughout a grid, each time they move that can pick a random cardinal direction up,down,left or right. They then rotate to face that direction using Quaternion.Slerp. However I noticed there were some edge cases where the agents didn't move at all, and found out the problem was being caused during rotations at 180 degrees. Doing some reading on this I found that Slerp and Lerp dont handle rotations at this degree very well if at all and now I'm at a loss on how to proceed. I tried using transform.rotateAround() to rotate the character around the Y axis to the direction, but again at 180 degrees the agents start to just spin in circles forever.

Here's my current rotate code:

IEnumerator rotate(){
while(Quaternion.Angle(transform.rotation,direction) > 0.3){
var tempRotation = Quaternion.Slerp(transform.rotation, direction, Time.deltaTime * rotateSpeed);
this.transform.rotation = tempRotation;
yield return null;
}
this.transform.rotation = direction;
}


Heres the code that handles picking where to go:

int choice = Random.Range(0,4);
prevPos = pos;
if((choice == 0) && pos.x < gs.maxX){
pos.x += 1;
direction = Quaternion.AngleAxis(-90,Vector3.up);
}
else if((choice == 1) && pos.x > 0){
pos.x -= 1;
direction = Quaternion.AngleAxis(90,Vector3.up);
}
else if((choice == 2)&& pos.y < gs.maxY){
pos.y += 1;
direction = Quaternion.AngleAxis(180,Vector3.up);
}else if((choice == 3) && pos.y > 0){
pos.y -= 1;
direction = Quaternion.AngleAxis(0,Vector3.up);
}


If someone could point me in the right direction on how to handle this gracefully I'd really appreciate it!

• Have you considered using Quaternion.RotateTowards instead? Apr 24, 2020 at 15:18
• It seems to work! but its a lot slower in its step compared to the other functions do you know why? or why this one differs from the other functions? Apr 24, 2020 at 15:36
• It gives you a speed parameter that you can adjust until it's as fast as you want it to be. Apr 24, 2020 at 15:37
• I know so do Slerp and Lerp im using Time.DeltaTime*rotationspeed and they havent changed but the rotations take a lot longer using lookToward  Apr 24, 2020 at 15:38
• No, Lerp and Slerp do not expose a speed, they expose a blend ratio, so 1.0 = jump all the way to the end, 0.0 = stay all the way at beginning, 0.5 = jump halfway in a single leap. (And the deltaTime adjustment you're using there is incorrect for this type of blend) RotateTowards takes a parameter in degrees like the documentation says, so 0.5 means rotate half a degree. Apr 24, 2020 at 15:40

Using Quaternion.RotateTowards() fixed my issue. Here's the new code:

IEnumerator rotate(){
while(Quaternion.Angle(transform.rotation,direction) > 0.3){
transform.rotation = Quaternion.RotateTowards(transform.rotation,direction,rotateSpeed*Time.deltaTime);
yield return null;
}
this.transform.rotation = direction;
}


Turns out upon further testing, this does not work. I have tried to modify it so that it will rotate around the Y axis in increments until the angle between agentPosition and the new destination is less than 180 degrees:

 IEnumerator rotate(){
angle = Quaternion.Angle(transform.rotation,direction);
while(angle > 0.3){
if(angle >= 180){
//There's problem with Slerp at angles >= 180 degrees so manually
// rotate around Y axis until Slerp can be used
transform.RotateAround(transform.position,Vector3.up,15*Time.deltaTime*rotateSpeed);
angle = Quaternion.Angle(transform.rotation,direction);
}else{
transform.rotation = Quaternion.RotateTowards(transform.rotation,direction,Time.deltaTime*(rotateSpeed*90));
}
angle = Quaternion.Angle(transform.rotation,direction);
yield return null;
}
this.transform.rotation = direction;
}


This however still does not work.