1 (edited by jarne 2020-08-06 11:39:21)

Topic: Best practice geofencing

I'm wondering what the best practice for geofencing would be.
What I want is for when my user to walk a route with 3d markers scattered on it and entering an X radius (10-200m) of said markers that they "unlock" it.

I've seen some geofencing examples and examples with BoxCollider, but I'm wondering what the best practice is for this kind of behaviour? And if there is an example that I can look at to get an idea of what to do.

I used to do this in Mapbox by calculating the distance between geo location of player and closest marker object in the scene. I've tried doing the same in my current project with Online Maps, but it seems that I'm doing something wrong with the OnlineMapsUtils.DistanceBetweenPoints (I keep getting 0 as the distance between two points, I think it's because they get transferred into doubles and lose the rest of the decimals, which makes the lat/lng "identical").

Any help would be appreciated!

I'm using 3d markers and the LocationServices player marker if that's important to know.

p.s. so far I'm loving this plugin, a lot of useful features and examples that I can chop into custom things to use.

Edit:
I've found this: http://infinity-code.com/atlas/online-m … ample.html
Which I can rewrite to do what I want to achieve, but it this the best practice?

Re: Best practice geofencing

First working example with the same mindset as what I did with Mapbox:

using UnityEngine;

public class UnlockingManager : MonoBehaviour
{
    [Header("Variables")]
    [Tooltip("Distance needed to unlock points in meters.")]
    public float distanceNeeded = 25f;

    private OnlineMapsLocationService locationService;
    private CreateMarkers markers;

    private void Start()
    {
        locationService = OnlineMapsLocationService.instance;
        markers = FindObjectOfType<CreateMarkers>();
        locationService.OnLocationChanged += CalculcateDistance;
    }

    private void CalculcateDistance(Vector2 location)
    {
        string closest_location = string.Empty;
        float closest_distance = 9999;
        foreach (OnlineMapsMarker3D marker in markers.spawned_objects)
        {
            float distance = OnlineMapsUtils.DistanceBetweenPoints(location, marker.position).magnitude * 1000;
            if(distance < closest_distance)
            {
                closest_distance = distance;
                closest_location = marker.label;
            }
            if (distanceNeeded > distance) Debug.Log($"{marker.label} unlocked!");
        }
        Debug.Log($"Closest location is {closest_location}, {closest_distance} meters away!");
    }
}

I'm pretty sure this isn't best practice, since it might take a lot of performance to do these calculations (I haven't tested it yet, let alone test it with a large set (40+ 3d markers)), but for now it works.
Still, if there is some kind of best practice I should be looking into I'd love to know!

Re: Best practice geofencing

Hello.

Three points about CalculcateDistance method:

1. DistanceBetweenPoints is a very slow method and it is best to minimize its use.
To do this, first calculate the distance in degrees between locations.
If the distance in degrees is less than 12 arc minutes (for example, 1/5 degree, ~360 meters) then use DistanceBetweenPoints to calculate the distance in kilometers.

2. For a correct result, it doesn't matter whether you calculate the distance in meters or kilometers.
If you calculate the distance in kilometers, you will save one multiplication per marker.

3. By using sqrMagnitude instead of magnitude, you will save Math.Sqrt per marker.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.