mapbox / mapbox-unity-sdk

Mapbox Unity SDK - https://www.mapbox.com/unity/
Other
725 stars 210 forks source link

Player position Android frequency update #1850

Open lukeholmes1986 opened 2 years ago

lukeholmes1986 commented 2 years ago

Hey @brnkhy

Hopefully I can throw one more question at you. Over the past 6 months we have been developing a Geo location project, it was constantly tested and as of around November/December of last year there were no "map" problems. Around this period you might know that Plastic SCM was forced on all unity projects as well as new versions of Unity released, we switched to the recommended release from 2020.3.12f1 to 26f1.

Around this time we started noticing that the frequency of the players location was dramatically reduced where you would be static for 3/4 + minutes at a time whilst moving then appear randomly at your current position. This was with full signal in open areas across multiple devices in different locations, all sharing the same behavior. Weve tried multiple "fixes" for this and the only thing that seems to be constant is if you disable all wifi/mobile data paths and only use GPS however because our app relies on mobile data heavily this is a difficult test to be accurate. Another point to add is that if we minimize then maximize the app or we lock the phone then unlock the position is updated, almost like its not running in the foreground (which it is)

We then thought it might be something in our code, so weve gone back to basics and tried the out of the box LocationbasedExample with no modifications at all. This also shows the exact behavior of "teleporting" across locations, so at this point we start thinking has Android done some sort of Location update that we cant find, we also tried the older version of Unity we originally developed on with the same behavior. Ive tagged a previous thread below that seems to discuss the same problem with no resolution.

So my question is, do you have any thoughts we could try and can you replicate this behavior using the location based prefab example in the SDK? Thanks !!

https://github.com/mapbox/mapbox-unity-sdk/issues/1280

Note: If this is a bug or support ticket, please provide the following information: Unity version: 2020.3.26f1 Models of phones tested: Pixel 3A, Pixel 4, Galaxy S21 Android Version 12 Scripting Backend: Mono Api Compatibility Level: Multiple tried but 29/30 is what we have been using Mapbox SDK version: Mapbox 2.1.1 The platform you're building to: Android A description of what you're trying to do: Understand why the frequency of updates has randomly changed

Markovicho commented 2 years ago

@lukeholmes1986 We are also not super happy with the current versions of the locationprovider (androidnative & default).We are experiencing similar issues like you describe and can confirm that it's an mapbox locationprovider issue while other services has no issues. So it's no "the gps was bad in this area" situation.

As far as I can tell the DefaultProvider is using Unitys builtin Input.Location Interface while DeviceLocationProviderAndroidNative.cs is using an custom native-plugin gathering the locationdata from the operating system. The code is really old and in the meantime google offered the option to use their FusedLocationProvider which combinses all available sensors/data ("fusion") to get the best results even in bad circumstance. This solution seems to be very very robust. So the power is there but it seems to be used neither by Unity's Input.Location nor the Mapbox plugin...

As the mapbox team is currently working on refactoring VectorFeature/AbstractMap i assume that it will take quite a while until this is on the roadmap (@brnkhy correct me if i am wrong).

What now ?

You could grab something like this to start with and put your own AbstractLocationProvider implementation above it: https://forum.unity.com/threads/released-fused-location-provider-plugin.1065359/

This plugin will use Androids FusedLocationProvider to provide the following container of information to c# scripts:

public struct FusedLocationResult { public double Latitude; public double Longitude; public bool IsError; }

This will not be enough to implement the AbstractLocationProvider (f.e orientation is missing) but based on what already in Mapbox-SDK it should be easy to adapt the code of DeviceLocationProviderAndroidNative.cs to work with other native plugins :-)

We will also look into this topic in a few months again and try to find a better solution. It would be great if we could share our insights and improvements so mapbox sdk could benefit from it. Let's not forget about that this is sdk is free to use and needs some support :-)

lukeholmes1986 commented 2 years ago

Hey @Markovicho Thanks alot for the reply, its glad to know were not alone with this problem!

The fusion plugin looks like it could be a workaround for the moment, have you tested it with success? I dont suppose your able to send an example of a your implementation of AbstractLocationProvider if you wrote one just so I can see how this should fit together?

We can worry about orientation etc at a later date, the position is fundamental to our app working. One thing I have just found here is the below block of text, could we just add this play service to consume the fusion provider if I'm reading this correctly?

Use Google's Fused Location Provider By default, the Maps SDK uses the Android GPS and Network Providers to obtain raw location updates. In applications using Android 11, the raw location updates might suffer from precision issues.

The Maps SDK also comes pre-compiled with support for the Google's Fused Location Provider. If your target devices support Google Play Services, add the following Google Play Location Services dependency to your project, and the Maps SDK will use the Google's Fused Location Provider in your application automatically:

implementation("com.google.android.gms:play-services-location:18.0.0")

I made a start writing a modified abstractLocationProvider but I want to try this play module first.

`using FusedLocation.Core;
using System;
using UnityEngine;

    namespace Mapbox.Unity.Location
{
    public abstract class AbstractLocationProviderFused : MonoBehaviour
    {
      public double LAT; 
      public double LONG; 
      protected Location _currentLocation;
      public void StartService()
      {
        FusedLocationAPI.StartService(2000, 1000, "Location permission denied", "Permission required toast", "Permission rationale location");
        FusedLocationAPI.GetLocation(OnReceiveLocation);
        FusedLocationAPI.SetPriority(FusedLocationPriority.PRIORITY_LOW_POWER);
      }

        /// <summary>
        /// Gets the last known location.
        /// </summary>
        /// <value>The current location.</value>
        public Location CurrentLocation
        {
            get
            {
                return _currentLocation;
            }
        }

        public event Action<Location> OnLocationUpdated = delegate { };

        protected virtual void SendLocation(Location location)
        {
            OnLocationUpdated(location);
        }

        private void OnReceiveLocation(FusedLocationResult result) 
        {
       // Debug.Log("[" + Time.time + "] Result: " + result.Latitude + "," + result.Longitude + "," + result.IsError);
        LAT = result.Latitude;
        LONG = result.Latitude; 
        }
    }
}
`
Rman99 commented 2 years ago

Hi, I have also been working on a Unity project which relies heavily on the Mapbox SDK location services. I can confirm that I am also experiencing the issue where the player location is only updated when the game is minimized/maximized. However this was not the case in December (and in the months prior to this) where the player location was being updated as expected (very frequently / near real-time) without issues. I can only assume that something has changed on the newest versions of the Android OS for this to have started happening so recently.

The issue can be re-created very quickly using the method by the original poster (creating a new Unity project, installing the Mapbox SDK, use the LocationBasedGame prefab and then installing on an Android device. I have not tested with an iOS device so cannot confirm if the issue is present there as well.

This seems like a fundamental issue with the SDK if the location services are not usable on Android devices. Hopefully this is a bug and not a compatibility issue between Mapbox SDK and Android which can be easily resolved (it would seem strange for the SDK to exist but not work as intended?). I am not an advanced developer so was really relying on the simplicity of the (up until now) amazing Mapbox SDK for my project. I am happy to help assist with any troubleshooting. testing, or contributions to getting this issue resolved!

Unity version: 2020.3.26f1 (have re-created the issue in a number of older versions) Models of phones tested: Pixel 3A Android Version 12 Scripting Backend: Mono Api Compatibility Level: Minimum 24, Target 29 (have re-created the issue with different levels) Mapbox SDK version: Mapbox 2.1.1 The platform you're building to: Android A description of what you're trying to do: Have the Mapbox SDK location services update the player position in relation to the map in real time (as it was previously).

lukeholmes1986 commented 2 years ago

FYI @Markovicho @brnkhy weve been doing some further investigation and it seems to be Android 12 specific the problem is discussed a few days ago here for Ludia and the google issue tracker is here from 2 weeks ago.

Android "we wont be fixing this till android 13" We are now trying a rollback of our android devices to 11

Rman99 commented 2 years ago

Hi, I have also looked more into this and there is an open Unity issue which could be related: https://issuetracker.unity3d.com/issues/android-input-dot-location-dot-start-doesnt-update-on-android-12

Reading these posts from Unity and Google it sounds like there might be a workaround for the issue on Android 12 but at the moment I'm non-the-wiser as to how this can be achieved.

lukeholmes1986 commented 2 years ago

Another note to add on testing, Ive just downgraded my phone to Android 11 latest build. Instantly the positions are updated as expected with the location providers, we are looking at modifying the the fused location script to see if we can get anything working whilst remaining on 12. So some update to android 12 in the past 2 months is the culprit for all of this by the looks of it.

brnkhy commented 2 years ago

Hey @lukeholmes1986, @Rman99, @Markovicho That's a great discussion going on here, I read it all, tried to understand the issue. I haven't done much device development before so I'm not familiar with location services. Last update from @lukeholmes1986 mentions it works well in Android 11 but not with 12; so do we know if this is an SDK issue or something between Unity&Android? I'm afraid I'm not much help at this point but I'll be following this ticket.

lukeholmes1986 commented 2 years ago

Hey @brnkhy its between Unity and Android here is the Unity bug. The below from Google being the root cause, however as a side note in case we havnt covered this in the topic, if you open google maps set a target direction then open our mapbox app, locations are updated as expected which makes us think theres a google maps permission issues going on here.

Thanks for this report. The root cause here is that while exposing LocationRequest as a public API in Android S, we chose to maintain compatibility with the existing LocationRequest behavior. However, this unintentionally caused unexpected behavior (LocationRequests with a quality = LOW) when using existing requestLocationUpdate() APIs. It is too late to change this behavior for S, but this will be fixed in Android T

lukeholmes1986 commented 2 years ago

Hey @brnkhy so we have modified the "Demo script" from the fusedLocation Provider that @Markovicho first linked as below to drop the gps refresh in the update loop (In reality this needs a 5 second delay or something) but we have tried this on an Android 12 device which updates the coords consistently. So with that being said could you help us with one of the following options 1) Can a modification be made to the Mapbox SDK to refresh the LAT/LONG in a similar fashion in some sort of loop to keep retrieving an update 2) How would we pass our own Coords into the SDK if we make use of this fusion provider?

`using FusedLocation.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Demo : MonoBehaviour
{
    [SerializeField] private Text _label = default;
    private bool _startService;

    void Update() 
    {
        if (_startService == true)
        {
            FusedLocationAPI.GetLocation(OnReceiveLocation);
        }
    }

    public void StartService()
    {
        FusedLocationAPI.StartService(2000, 1000, "Location permission denied", "Permission required toast", "Permission rationale location");
        FusedLocationAPI.GetLocation(OnReceiveLocation);
        FusedLocationAPI.SetPriority(FusedLocationPriority.PRIORITY_HIGH_ACCURACY);
        _startService = true;
    }

    public void StopService() {
        FusedLocationAPI.StopService();
        _startService = false;
    }

    private void OnReceiveLocation(FusedLocationResult result) {
        Debug.Log("[" + Time.time + "] Result: " + result.Latitude + "," + result.Longitude + "," + result.IsError);
        _label.text = "Result: " + result.IsError + " (" + result.Latitude + ", " + result.Longitude + ")";
    }
}`
bfischlin94 commented 2 years ago

@lukeholmes1986 I am struggling with the same issue, and Android 12 is now released for many devices already. Did you get it to work eventually ? If so, could you share the script(s) you used ? Thank you :)

lukeholmes1986 commented 2 years ago

Hey @bfischlin94 no script changes required. I updated the Unity bug post below, but if you try the latest Beta release of unity (2022.1.0.b11) and ensure you have the latest android patch releases (which went out at the start of March) we found the issue was resolved. Unity put some patch notes that this fix was backported into earlier versions however our tests showed the locationProvider problem still existed there. So upgrade unity>Patch android device to latest should fix it. FYI test platform was a Google PIxel 4 for reference. Please drop another comment here if this works for you so we can have multiple tests confirming this.

https://issuetracker.unity3d.com/issues/android-input-dot-location-dot-start-doesnt-update-on-android-12

bfischlin94 commented 2 years ago

@lukeholmes1986 Thank you for your reply! I can confirm it worked using Unity 2022.1.0.b12 and a Pixel 6 with Android 12