Look at object with a single axis while moving.

Ok, so I have a central object (an arrow) that rotates around a circle, pointing towards the direction the camera is facing. I have an empty gameObject parented to the center of the camera as a reference Vector3 to look towards. The arrow is a Sprite, so it’s only supposed to be rotating on the Z-axis. Using a few snippets I found, I managed to get it working perfectly with this:

var newRotation : Quaternion = Quaternion.LookRotation(facingVel.transform.position - cursorObj.transform.position, Vector3.forward);
newRotation.x = 0.0;
newRotation.y = 0.0;
facingVel.transform.localRotation = newRotation;

The problem I have now is that the player object must be able to rotate, however as soon as the player isn’t at 0,0,0 rotation, this throws off the above code and the arrow begins drifting, due to the position of the target in world space. The arrow is also parented to something, if that helps.
Any ideas?

EDIT:
I still haven’t found the solution, however after exposing some of the values, I’ve noticed that the Z and W components of the newRotation variable change significantly as the player object is rotating.

attach the object to your camera

Okay, I think I understand well enough what you’re trying to do. Sorry I haven’t been able to follow your train of thought on this as well as you might like. If it’s not exactly what you’re needing, hopefully this will at least get you pointed in the right direction.

Going along with the idea of a compass again, what you’ll need are:

  1. Your script will need to know the camera’s current heading, so you’ll probably want a Transform variable to hold that.

  2. You’ll need to know the local orientation of your square pointing you in the right direction. I’ll assume that no rotation faces towards a camera with no rotation.

So, here’s my general idea of how to approach this, on the basis that it’s a fixed-orientation compass.

var mainCam: Transform; // Connect your camera to this either through the editor or script

// ...

facingVel.transform.localEulerAngles = Vector3(0, 0, Mathf.Repeat(mainCam.eulerAngles.y, 360.0));

Based on the criteria mentioned above (especially #2), this is a very simple and straightforward approach to directly converting the Y-axis rotation of the camera to the Z-axis rotation of the arrow. If the arrow is indeed already a child of the player and/or camera in some capacity, then it should be able to rotate with local rotation alone.

If it needs more than that, however, a slight tweak can potentially be employed instead:

facingVel.transform.rotation = Quaternion.LookRotation(mainCam.position - facingVel.transform.position, Vector3.up); // Set a new forward direction to face the camera
facingVel.transform.rotation *= Quaternion.AngleAxis(Mathf.Repeat(mainCam.eulerAngles.y, 360), transform.forward);

I believe I got the order right on this, at least. As Quaternion math is non-commutative, it can be easy to mix up the exact order of operations.

This version faces the arrow toward the camera with “world up” as its upward direction. Then, it rotates the arrow while facing directly toward the camera to match the degrees of rotation, acting as an effective compass.

If this still isn’t able to get you where you’re trying to go with this, just let me know!

var newRotation : Quaternion = Quaternion.LookRotation(facingVel.transform.position - cursorObj.transform.position, Vector3.forward);
newRotation.x = 0.0;
newRotation.y = 0.0;
facingVel.transform.localRotation = newRotation;

So lets look at what you did here:

  1. you used lookrotation with agruements of a direction and vector 0,0,1, which is right.

  2. You adjusted the rotation’s x and y value to 0 to only rotate in z, but this is where you made a mistake. The variable newRotation right now is a Quaternion, it is not the transform.rotation you see on the inspector. You should not ever directly adjust the Quaternion unless you know what you are doing. The correct way to fix this is instead of adjusting x and y the way you did, instead do the following:

    facingVel.transform.rotation = newRotation;
    facingVel.transform.eulerAngles = new Vector 3 (0,0,facingVel.transform.eulerAngles);

What I did here is applied the newRotation, a Quaternion, to transform.rotation, which is also a Quaternion. The numbers you see in the rotation section on the inspector is really transform.eulerAngles instead. So to make sure no rotation happened on x and y, you just need to adjusted the eulerAngles.

I don’t know what exactly you want to do, but this seems to be the main problem.