'Get Unity compass true north heading

I'm currently trying to implement a location-based AR app for Android using Unity C# and ARCore. I have managed to implement an algorithm which gets latitude/longitude and translates it to unity meters. However, this is not enough to place objects at a GPS location since the orientation of the world will be off if you do not align the unity scene with the real world orientation.

Anyway, the problem with the compass is that I cannot find a way to align an object with the true north. I have tried aligning an object with true north by using transform.rotation = Quaternion.Euler(0, -Input.compass.trueHeading, 0);

However this causes the object to constantly change rotation based on where my phone's heading so in a way true north is always changing. What I am currently trying is:

var xrot = Mathf.Atan2(Input.acceleration.z, Input.acceleration.y);
var yzmag = Mathf.Sqrt(Mathf.Pow(Input.acceleration.y, 2) + Mathf.Pow(Input.acceleration.z, 2));
var zrot = Mathf.Atan2(Input.acceleration.x, yzmag);

xangle = xrot * (180 / Mathf.PI) + 90;
zangle = -zrot * (180 / Mathf.PI);
TheAllParent.transform.eulerAngles = new Vector3(xangle, 0, zangle - Input.compass.trueHeading);

This seems to be working better since the object will point towards a single direction with minimum shaking/jittering of the object due to erratic compass reading but points in one direction nonetheless. However, the problem with this is that it points to a different direction every time the app starts, so true north is never in one place according to the code. However the compass readings are fine as I have checked the readings against other GPS apps which implement a compass.

  • I have also tried transform.rotation = Quaternion.Euler(0, -Input.compass.magneticHeading, 0); but this gives the same always-changing result as the first one. Any help would be appreciated.


Solution 1:[1]

its how i solve this issue in my project i wish it help you.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class newway : MonoBehaviour
{
  
    GameObject cam;
    void Start()
    {
        
        cam = Camera.main.gameObject;
        Input.location.Start();
        Input.compass.enabled = true;
    }

    void Update()
    {
        
        Quaternion cameraRotation = Quaternion.Euler(0, cam.transform.rotation.eulerAngles.y, 0);
        Quaternion compass = Quaternion.Euler(0, -Input.compass.magneticHeading, 0);

        Quaternion north = Quaternion.Euler(0, cameraRotation.eulerAngles.y + compass.eulerAngles.y, 0);
        transform.rotation = north;
    }

}

Solution 2:[2]

Possibly, your GameObject is rotating on its own axes, but you need your GameObject to pivot around the camera, or the center.

If that's the case, try creating another empty GameObject, and set its position to (0, 0, 0), or wherever you wish the center to be. Then add original GameObject as a child to this new one.

Apply your transform.rotation script to this new GameObject.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 faryar76
Solution 2 aamir