Let’s say I have a spherical planet and a character moving around on it.
How would you calculate the angle a compass indicating north (top of the sphere) would have to show?
I have now the following script attached to the compass image, jumps around when getting close to pointing to North or South and do not understand why (north is a gameobject on the of the sphere)
public class Compass : MonoBehaviour
{
public Transform player;
public Transform north;
private Vector3 dir;
void Update()
{
Vector3 diff = north.position.normalized - player.position.normalized;
dir.z = Vector3.SignedAngle(diff, player.forward, player.up);
transform.localEulerAngles = dir;
}
}
I think this is happening as my vect diff is not tangential to the sphere syrface, but pointing “through” the sphere to the north. ANyone can help me fix this?
Well, all you have to do is take the north-south vector and project it onto your “compass plane”. This would work everywhere on the planet except at the poles where that vector would be perpendicular to the plane.
A compass does not point to a certain point but the needle aligns with the magnetic field lines which goes from north to south.
From your code it’s not really clear on what kind of object this script is attached to. You usually have a “casing” that you actually hold and that rotates with “you” and it contains the needle that can rotate and should align with the north / south direction. Since you’re currently setting the localEulerAngles I would assume this script is attached to the needle?
The way you use SignedAngle would not work because SignedAngle does not project the directions onto the same plane. The third normal / reference vector is only used to determine the sign of the angle. So the method still calculates the angle the same way as Vector3.Angle does, it just returns a signed angle. You could use SignedAngle once your two vectors are in the same plane. You can use Vector3.ProjectOnPlane and use your players up vector as normal. Once you projected the north-south direction onto your compass plane you should be able to use SignedAngle to determine the relative angle. Though there are way too many unknowns regarding your setup to be more specific.
This script would be attached to a UI image showing a compass image that is supposed to turn around as a ship navigates a globe. the ‘north’ transform is an empty gameobject here that sits on teh top of the planet. I hope that makes more sense
I got it to work (with help of a friend) by adding a few cross products into the mix.