I am having trouble rotating an object about a relative axis

There is an object with an arbitrary rotation. I want to rotate it about its local X, Y, or Z axis. By this definition, the object’s right, up, or forward vectors would remain unchanged for each respective axis. When I try to do this with quaternions, it does not behave as expected:

// For the X axis only:
target.transform.rotation *= Quaternion.AngleAxis(1, target.transform.right);

When I do this, the object rotates in some seemingly random direction and the right vector changes. What am I doing wrong? It works fine when the object is in its initial rotation with euler angles <0, 0, 0>.

Other potential solutions that I have tried involve using a LookRotation with a varying up vector, parenting the object in another object and modifying its local rotation, and screwing with raw euler angles.

Thanks in advance.

IMAGES: Unexpected behavior - Album on Imgur

Reading this, I have no idea what you’re visually referring to or trying to achieve. Posting an image will help clarify for everyone.

Yes, of course.

Does that help clarify the problem?

Hi!

The order in which you multiply Quaternions matters. If you want to rotate a rotation by something, that something needs to come first. So go with transform.rotation = Quaternion.AngleAxis(...) * transform.rotation;

Cheers,
Pärtel

I now see why this is necessary, but the problem does not yet seem to be fixed. Would you mind taking another look?

In my code, I instantiate a sphere every frame in the direction of the object’s right vector. It does not stay the same, and I have illustrated its path in black in the image below.

var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = target.transform.position + target.transform.right;

target.transform.rotation = Quaternion.AngleAxis(1, target.transform.right) * target.transform.rotation;

I’ve also found another inconsistency in the expected behavior - when I use the LookAt method on the transform, it produces similar crap.

var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = point;

target.transform.LookAt(point);

In this case, the variable point is the position on an invisible plane intersecting the object, coplanar with the axes control pictured below.

I’m sure that you would agree that it’s not looking at any of those points…