I am working on a 3D game where you can control an object that orbits a sphere with an on-screen virtual joystick. So far I have that part working, but the object follows the joystick angle perfectly and "snaps" into the angle, rather than smoothly interpolating to the new angle of the joystick.

I would like to redo this and have it interpolate the values. I have it very close using the following code:

angle = Mathf.Atan2(joystickY, joystickX) * Mathf.Rad2Deg;
Quaternion targetRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, currentAngle);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, TURNING_SPEED * Time.deltaTime);

This works great on one side of the sphere, but as soon as I move the object halfway around the sphere, the rotation is now mirrored and the object rotates 180 degrees until it reaches the other side again. What am I missing here?

I am basically trying to calculate the joystick angle, then apply that to the object as it orbits, but do this smoothly using slerp.

Let me know if you need any further information. Thanks!

  • \$\begingroup\$ Changing just one angle out of a set of Euler angles can be dicey, since the meaning of that axis can depend on the other two. Can you show us an image/animation or diagram of how your object is set up, so we understand what set of orientations we can expect coming in from transform.rotation? \$\endgroup\$
    – DMGregory
    Nov 14, 2017 at 1:14
  • \$\begingroup\$ @DMGregory Well it looks like I just figured this out after all! All I had to do was use transform.localRotation instead of transform.rotation... Oops haha \$\endgroup\$
    – DRiFTy
    Nov 14, 2017 at 1:47

1 Answer 1


For anyone running into a similar issue, the solution (for me at least) was to just change it to rotating around the local z-axis rather than the world z-axis:

joystickAngle = (Mathf.Atan2(-joystickY, -joystickX) * Mathf.Rad2Deg) + 90;
Quaternion targetRotation = Quaternion.Euler(0f, 0f, joystickAngle);
var blend = 1f - Mathf.Pow(1f - 0.1f, Time.deltaTime * 60f);
thisTransform.localRotation = Quaternion.Lerp(thisTransform.localRotation, targetRotation, blend);
  • \$\begingroup\$ I'm glad you solved it! Just note that your deltaTime correction needs a bit of adjustment to work correctly for the exponential ease-out you're using. See the bottom of this answer for details. \$\endgroup\$
    – DMGregory
    Nov 14, 2017 at 2:33
  • \$\begingroup\$ @DMGregory Thanks! I didn't realize that it isn't a linear ease... Makes total sense too. I adjusted my answer to include the new changes for an exponential ease using lerp instead of slerp. The effect is definitely smoother, and looks better. Appreciate it! \$\endgroup\$
    – DRiFTy
    Nov 14, 2017 at 2:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .