Hi, I’m building a geo-localisation game where people have to go to a specific location.
I want to display a map of their surroundings, and place markers on that map to indicate
- where the player is
- the target location
I found some bits of code on the net that allows me to turn a gps coordinate into an in-game coordinate, but the problem is that the result is always a few (about 20 or so) meters off. But 20m is a lot for the purpose of my app.
All the code I found assumes that the earth is a sphere, but since the earth is not exactly a sphere I guess that’s where my difference comes from. Here’s the code I’m currently using.
public static Vector3 GpsToGameCoord(Vector2 gpsCoordinates, float scale)
{
Vector3 result = Vector3.zero;
// latitude is vertical, longitude is horizontal, so we need to inverse the values.
result.y = gpsCoordinates.x * Mathf.Deg2Rad * earthRadius;
result.x = gpsCoordinates.y * Mathf.Deg2Rad * earthRadius;
result *= scale;
return result;
}
Is there a library out there that I could use to have more precision? An asset would work too, but I don’t need a full blown geolocalisation asset bundled with all kinds of thing I don’t need.
Edit: answered some questions in the comments
I’m using official gouvernement maps (the ones they use in the military etc…) the projection is Lambert2008 ( http://www.ngi.be/FR/FR2-1-7.shtm )
The waypoints coordinates come from Google maps, they’re entered directly in the inspector, so don’t rely on GPS accuracy. The player location however depends on device GPS, obviously.
The game always happen at the same location (it’s for a hotel resort, game happens in the woods nearby), so I only need a tiny patch of map like you say…
For simplification, my map always points north, I don’t try to rotate it according to player orientation. To position the waypoints, I pick a point on the map as my center point (recognisable landmark, so I can have accurate GPS coordinates from google maps). All the waypoints and player ping are positioned relative to that center point using my GpsToGameCoord method.
To scale my map properly, I pick three coordinates to triangulate the distance between each of them, and then scale the map manually in the editor (of course keeping the same aspect ratio) so that the waypoints match their location on the map. My problem though, is that with the waypoints I get, there is no way to scale the map in order to achieve a satisfying correspondance to my triangulation.
Followup:
I modified the GpsToGameCoord method when I realised the radius I’m using should be the radius of the latitude circle at my coordinates, and not the earth radius. I know it’s still an approximation, because the method still assumes the earth is a sphere and not an elipsoïd.
public static Vector3 GpsToGameCoord(Vector2 gpsCoordinates, float scale)
{
Vector3 result = Vector3.zero;
// latitude is vertical, longitude is horizontal, so we need to inverse the values.
result.y = gpsCoordinates.x * Mathf.Deg2Rad * poleRadius;
result.x = gpsCoordinates.y * Mathf.Deg2Rad * eqRadius * Mathf.Cos(gpsCoordinates.x * Mathf.Deg2Rad);
result *= scale;
return result;
}
Here’s what the problem was with the old implementation:
Here’s what the game looks like with the new implementation of my method. Everything is actually much closer.
As you can see it’s a lot better.