How do I ignore rotation on certain axis?

private void TransformRotationHandler() {
    var rotationDirection = WaypointPosition - movingObject.transform.position;
    if (rotationDirection == Vector3.zero) return;
    if (ignoreXRotation) rotationDirection.x = 0;
    if (ignoreYRotation) rotationDirection.y = 0;
    if (ignoreZRotation) rotationDirection.z = 0;
    var rotation = Quaternion.LookRotation(rotationDirection);
    movingObject.transform.rotation = Quaternion.Lerp(movingObject.transform.rotation, rotation,
        Time.deltaTime* rotationSpeed);
}

So I have the following code and I’m trying to make it so if any of the ignore rotation bools are true it ignores the rotation on that certain axis (Meaning it doesn’t touch it, the issue is that this code just rotates the ignored rotations to 0 and I don’t know what I’m supposed to change it to in order to just not touch the rotation on that axis) but it isn’t working. So what should I do to properly ignore the rotation?

Instead of setting it to zero, set it to what the current rotation on the object is:

var currentRotation = movingObject.transform.rotation.eulerAngles;
if (ignoreXRotation) rotationDirection.x = currentRotation.x;
if (ignoreYRotation) rotationDirection.y = currentRotation.y;
if (ignoreZRotation) rotationDirection.z = currentRotation.z;

As an aside, you’re making a common mistake with Lerp which will make this rotation not smooth and never reach the target rotation. The first two parameters should stay the same frame-to-frame (your fixed start and end rotations), and the third parameter should move smoothly from 0 to 1 across the time period that you want the rotation to take.

1 Like

This worked perfectly thank you! Also are you sure that I’m using Lerp incorrectly? From what I’ve seen it rotates perfectly. If I am using it incorrectly though how exactly would I fix it so it stays between 0 and 1?

The way you are using it currently is like this:

Each frame you are looking at your current rotation and your target rotation. Then you are moving your rotation to some percentage of the remaining rotation. The percentage is Time.deltaTime * whatever your rotation speed is. So your rotation will go something like this (I made up some numbers for an easy example):

Let’s say you have your rotation set to 50.
Let’s say your frame rate is a constant FPS and each frame takes .016 seconds.
Therefore each frame your “t” parameter will be (50 * .016) = 0.8, which means you will move 80% of the remaining way towards your target rotation.

Frame 1: current rotation: 0°, target rotation = 100°. 80% of 100 is 80. Result = 80°
Frame 2: current rotation: 80°, target rotation = 100°. 80% of 20 is 16. Result = 96°
Frame 3: current rotation: 96°, target rotation = 100°. 80% of 4 is 3.2. Result = 99.2°
Frame 4. current rotation: 99.2°, target rotation = 100°. 80% of .8 is .64. Result = 99.84°

And so on forever. You will never actually reach 100° of rotation because you are only moving 80% of the way there each frame.

The way to use Lerp properly is the following:

As soon as you know what your target rotation is, save it in a variable. Also save your current rotation in a variable. In your case your target direction is what we calculated as “rotation” in your example code. So as soon as you set WaypointPosition do the following calculation:

Quaternion startRotation;
Quaternion targetRotation;
float startedRotatingAt;
float willEndRotatingAt;
bool isRotating = false;

void SetupForLerp() {
    var rotationDirection = WaypointPosition - movingObject.transform.position;
    if (rotationDirection == Vector3.zero) return;
    var currentRotation = movingObject.transform.rotation.eulerAngles;
    if (ignoreXRotation) rotationDirection.x = currentRotation.x;
    if (ignoreYRotation) rotationDirection.y = currentRotation.y;
    if (ignoreZRotation) rotationDirection.z = currentRotation.z;
    var rotation = Quaternion.LookRotation(rotationDirection);

    startedRotatingAt = Time.time;
    // Our starting rotation is the current rotation
    startRotation = movingObject.transform.rotation;
    // Our ending rotation is what we calculated above...
    targetRotation = rotation;

    float degreesToRotate = Quaternion.Angle(startRotation, targetRotation);
    float timeItWillTake = degreesToRotate / rotationSpeed;
    willEndRotatingAt = Time.time + startedRotatingAt;
    isRotating = true;
}

Then, in TransformRotationHandler() do this:

private void TransformRotationHandler() {
  if (!isRotating) {
    // No need to do anything if we're not currently doing a rotation
    return;
  }

  // How far between startedRotatingAt and willEndRotatingAt are we? This function will return 0 if we just started, .5 if we're halfway between them, .9 if we're 90% of the way there, 1 if we're at the end time, etc.
  float t = Mathf.InverseLerp(startedRotatingAt, willEndRotatingAt, Time.time);
  movingObject.transform.rotation = Quaternion.Lerp(startRotation, targetRotation, t);

  if (t >= 1) {
    // We're done rotating for now.
    isRotating = false;
  }
}

Note that “rotationSpeed” is expressed in degrees per second. So you might have to change the value to get the speed you want. But the speed will now be constant across the whole rotation.

timeItWillTake is never used and when running this code it doesn’t seem to be rotating at all, where am I supposed to put timeItWillTake?

Oops!

I made a typo near the end of SetupForLerp:

willEndRotatingAt = Time.time + timeItWillTake;

Also I didn’t test the code… so there might be bugs :stuck_out_tongue: