Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

3D Physical Compass in Unity (Handling Rotation)

Discussion in 'Scripting' started by Cal_Mac, Jan 9, 2020.

  1. Cal_Mac

    Cal_Mac

    Joined:
    Feb 4, 2018
    Posts:
    22
    Looking for help towards Rotation in Unity, I have a hand held 3D Compass and I have the hand pointing 'north' which is an empty transform. I'm trying to lock the rotation of the hand so when the compass is tilted, the hand still accurately looks for north.

    The problem is, when tilted the hand pops out of the compass.

    Here is the following code I have so far and a picture of the issue below.


    Code (CSharp):
    1. public Transform target;
    2. public float speed = 1.0f;
    3.  
    4. // Start is called before the first frame update
    5. void Start()
    6. {
    7.  
    8. }
    9.  
    10. // Update is called once per frame
    11. void Update()
    12. {
    13.     var lookPos = target.position - transform.position;
    14.     lookPos.x = 0;
    15.     var rotation = Quaternion.LookRotation(lookPos);
    16.     transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * speed);
    17. }
     

    Attached Files:

  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    You'll need a reference to the transform of the compass housing itself, not just the needle. Then, you can calculate the rotation in the local space of the housing. (Haven't tested the code below, but it should be close at least)
    Code (csharp):
    1. public Transform north;
    2. public Transform housing;
    3. public float speed;
    4.  
    5. void Update()
    6. {
    7.    var lookPos = north.position - transform.position; // assumes this script is attached to the needle
    8.    var housingLocal = housing.InverseTransformPoint(lookPos); // change of coordinates from world space to housing space
    9.    var localProjection = new Vector3(housingLocal.x, 0, housingLocal.z); // Remove the vertical offset so that we will look along the plane of the housing
    10.    var worldProjection = housing.TransformPoint(localProjection); // change of coordinates back into world space
    11.  
    12.    var rotation = Quaternion.LookRotation(worldProjection);
    13.    transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * speed);
    14. }
     
  3. Cal_Mac

    Cal_Mac

    Joined:
    Feb 4, 2018
    Posts:
    22
    Hi Wallace,

    Thanks for coming to my rescue again, the script you provided is definetely a step in right direction.

    It now consistently sticks with the compass housing, however not currently the right way - It currently points out of the face. I wonder if that may be something to do with the origin points of the mesh's im using.
     
  4. Cal_Mac

    Cal_Mac

    Joined:
    Feb 4, 2018
    Posts:
    22
    I've attempted to use Empty Gameobjects to correct any misaligntments but no joy. I'll keep tinkering.
     

    Attached Files:

  5. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    I did assume that the y-axis is pointing out the top of the housing. I'm not sure if that's how you have it set up though.

    EDIT: That is, north-south is the z axis, east-west is the x axis, and up-down is the y axis.
     
  6. Cal_Mac

    Cal_Mac

    Joined:
    Feb 4, 2018
    Posts:
    22
    Still no joy, can't seem to find any assets either that have a fully functioning compass.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,806
    I wrote one of these a while back. See attached. Press Play and then in the inspector window rotate the Y axis of the GameObject called PlayerAircraft. It's not precisely your problem but it's a trivial way to drive one rotation axis with the output from another axis.
     

    Attached Files:

    Cal_Mac likes this.
  8. Cal_Mac

    Cal_Mac

    Joined:
    Feb 4, 2018
    Posts:
    22
    Thank you Kurt!

    I just set the rotation of the needle to the rotation the player is facing and it seems to work, surprising! Thanks for your input and hopefully will help people in the future
     
    Kurt-Dekker likes this.
  9. Desktopdaydreams

    Desktopdaydreams

    Joined:
    Nov 20, 2010
    Posts:
    154
    Hi @Cal_Mac,

    Sorry to drag this old thread up but it looks like I've run into a similar problem.

    I have a 3D Physical Compass which is being held in the palm of the players hand. Rather than a needle I have a disc which is constantly pointing to north. As the player moves, they can tell which direction they are travelling, very similar to how the compass in Firewatch works.



    I've used @WallaceT_MFM script above which seems to work for the most part except that the disc seems to rotate out of the compass housing rather than just around its local Y axis. It seems to be a similar problem you had?

    Did you eventually solve it with code or was it a hierarchy issue? My compass' "disc" is parented to the compass housing which in turn is parented to a camera.

    EDIT: I have it setup as: north-south (z axis), east-west (x axis) and up-down is the y axis.

    Cheers
     
    Last edited: Jun 22, 2021
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,806
    Most likely the compass geometry is oriented wrong, such as an FBX / Blender import often sets its rotations to (-90, 0, 0).

    Redo the compass geometry to include an extra transform that is oriented correctly, and parent the visible geometry to that. Then only rotate the base transform.
     
  11. Desktopdaydreams

    Desktopdaydreams

    Joined:
    Nov 20, 2010
    Posts:
    154
    Apologies for the delay @Kurt-Dekker and many thanks for the pointers. I had already tried am extra transform both as a game object and through exporting a nested transform from the 3D package. I played around with various pivots and values but none seemed to work. I found another solution in the end but thanks again for the help.
     
    Kurt-Dekker likes this.