Easier way to flatten a rotation?

I have a rotation on a transform. I want to change it so that - if it were in Euler angles - I would zero out all the axis except X. And honestly the Z axis should be zero anyway, so it’s really just zeroing the Y axis.

But I don’t see any simple functions to zero out everything but the pitch, nor to zero just the yaw. In fact, since the rotation is stored as a quaternion, the only way I see to do this is get the rotation, convert it to Euler angles, make my modification, and then convert that back a quaternion.

So my code looks like this:

Vector3 tempAngle = fireOrigin.eulerAngles;
            tempAngle.y = 0;
            fireOrigin.rotation = Quaternion.Euler(tempAngle);

I feel like there should be a better way. Is there? Is there a simpler operation I can directly apply to the quaternion that would give me the same result?

I have this extension method:

public static Vector3 With(this Vector3 origin, float? x = null, float? y = null, float? z = null)
    {
        return new Vector3(x ?? origin.x, y ?? origin.y, z ?? origin.z);
    }

it does exactly what you say (if I understand your needs correctly) but you can for example make the call like fireOrigin.eulerAngles = fireOrigin.eulerAngles.With(y: 0f) and it looks nicer.

Not sure if that helps, it still creates a new vector but it’s a direct application.

2 Likes

Huh, that is a very clever extension method, I like it!

Outside of taking extra lines (which @johannesgaebler 's extension method takes care of elegantly) , there’s a more serious problem with this, which is basically that Euler angles are terrible. If you divide up the three components of an Euler angle, they can become almost meaningless.

I made a video with a more thorough explanation, but in short, you may get unpredictable behavior if you just flatten a Euler angle set this way. For any given rotation there are many different ways to represent that rotation as Euler angles and you can’t reliably predict which of those ways you’ll get back after the conversion; as a result, the X and Z might be angles that create nonsense after you set Y=0. (This is a mathematical reality of quaternion-to-euler conversion)

1 Like

Okay, then what would you recommend?

Because I’ve discovered that I am getting wonky results.
I think part of the problem is that I’m working with a rotation that is a child of another object.
My “firePoint” is attached to the front of my character. When my character rotates, the firePoint is now pointing in a new direction. It works well.
But I’m trying to set up some auto-aim mechanics. It works pretty well for most situations; I use “LookAt” on the firePoint to have ti face what I’m targeting, and when I am no longer targeting anything I set the local rotation to identity, and it’s back to pointing forward.
But for some weapon types I need that auto-aim to only adjust the yaw.

And when I tried that example I used earlier, well, it doesn’t quite work like I expected it to.

With the setup you have, the easiest thing to do is to probably to change the point you’re LookAt’ing towards. If you set targetPoint.y = transform.position.y, you’ll adjust the yaw.

1 Like