Compass - Point to target issue

I am trying to use a UI image to point towards my game objective in a topdown 3d style setup, the issue I am having is my compas is only half working and is tracking my object on the x and y axis instead of the x and z.

Any ideas or hints where I am going wrong?

        Vector3 compasImage = target.transform.position;
        transform.LookAt(transform.position + transform.forward, compasImage - transform.position);

Assuming the object you attach the script to wants to point towards the target, but keep its up direction, try

Vector3 direction = target.transform.position - transform.positon;
Vector3 up = transform.up; // you don't want this to change by the compass rotation
transform.rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(direction, up), up);

But I need more information. Is your compass 3d and how is it oriented (I mean the entire device, not just the spinning disc). And in what direction does the arrow point in the local coordinate system of the object you attach that script to?

The game is 3d with a fixed topdown view but the compass is only a 2d UI image on a canvas, so I want to track x&z I think and only transform the compass/images z rotation?

Gave your code a quick try(thank you) and its track the axis but transforms the image in 3d space instead just on the one axis.

The main problem with my original snippit of code is that it seems to track x&y instead of x&z movement.

Then you need to define the reference point, because if the compass is on the canvas, it does not have a 3d world position you can use.
To just get the z component of a rotation, try Quaternion.Euler(0,0,rotation.eulerAngles.z) where rotation is the full 3d rotation.

Sorry Im not quite following code wise, I tried

        Vector3 direction = target.transform.position - transform.position;
        Vector3 up = transform.up; // you don't want this to change by the compass rotation
        transform.rotation = Quaternion.Euler(0, 0, target.transform.eulerAngles.z);

and

Vector3 direction = target.transform.position - transform.position;
Vector3 up = transform.up; // you don’t want this to change by the compass rotation
transform.rotation = Quaternion.Euler(0, 0, transform.eulerAngles.z);

but I ended up with no movement at all, I then thought I could maybe cheat and just disable the mesh on the 3d object and run away with its rotation but I get a error with my line at the end.

“Cannot modify the return value of ‘Transform.rotation’ because it is not a variable”

or that it is read only if I just use compass.transform =…

Vector3 direction = target.transform.position - transform.position;
Vector3 up = transform.up; // you don’t want this to change by the compass rotation
transform.rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(direction, up), up);
compass.transform.rotation.z = gameObject.transform.rotation.y;

Sorry for being a pest, and thank you for the help!

Edit
Compass is defined as a gameobject
I also tried
compass.transform.rotation = Quaternion.Euler(0, gameObject.transform.rotation.y, 0);

but for some reason that seems to do nothing at all to my images rotation.

So first you tried transform.rotation = Quaternion.Euler(0, 0, target.transform.eulerAngles.z); but that copies the z part of the rotation of the target to the compass, but you don’t really care how your target is rotated, right?
try

Quaternion lookRotation = Quaternion.LookRotation(target.transform.position - reference.transform.position);
transform.rotation = Quaternion.Euler(0,0,lookRotation.eulerAngles.z);

where reference is whatever you want to point from. Probably your player object.

And in compass.transform.rotation = Quaternion.Euler(0, gameObject.transform.rotation.y, 0); should be compass.transform.rotation = Quaternion.Euler(0, gameObject.transform.rotation.eulerAngles.y, 0);, but I think it is really the z component you want to keep, if it is on a canvas.

1 Like

It is indeed and thank you very much for your time! All working now! what I ended up with was

    void Update()
    {
        Vector3 direction = target.transform.position - transform.position;
        Vector3 up = transform.up; // you don't want this to change by the compass rotation
        transform.rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(direction, up), up);
        compass.transform.rotation = Quaternion.Euler(0, 0, gameObject.transform.rotation.eulerAngles.y);
    }

One weird problem though, the rotation works fine for the 3d object but it gets reversed on the 2d image. for example if the object is moved left the 3d object rotates left but the image rotates right :smile:

I think your last problem is just a sign issue. Make it

compass.transform.rotation = Quaternion.Euler(0, 0, -gameObject.transform.rotation.eulerAngles.y);
1 Like

You sir are a good man, thanks again.

You are welcome :slight_smile: have fun coding