Unity obtains mobile phone location information

Unity obtains mobile phone location information

introduction

During the development of the game, sometimes it is necessary to obtain the player's location information, such as displaying the country and city where the player is located.

There are the following methods for reference:

  • It can be judged according to the region and language of the mobile phone.

  • Judging the location based on the IP, Alibaba Cloud has corresponding interface services.

  • Judging by GPS.

The above methods have their own advantages and disadvantages. Here is a brief introduction to the solution based on GPS.

accomplish

Unity does not provide the function of directly obtaining which country or city the player is in, but only provides the function of obtaining some GPS information, so we need to obtain specific countries and cities based on GPS information, which requires the help of some third-party plug-ins to achieve.

Unity obtains the user's latitude and longitude information

Official documentation: Unity - Scripting API: LocationService.Start (unity3d.com)

I made some modifications according to the official documentation. When requesting permission, because I used Unity2019, the interface provided by Unity does not support callback return, so I did some processing here.

The complete code is as follows:

using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Android;
using UnityEngine.Events;

/// <summary>
/// GPS位置管理器
/// </summary>
public class LocationManager : MonoBehaviour
{
    
    
    #region 单例
    public static LocationManager _Instance;
    public static LocationManager Instance
    {
    
    
        get
        {
    
    
            if (_Instance == null)
            {
    
    
                GameObject obj = new GameObject("LocationManager");
                _Instance = obj.AddComponent<LocationManager>();
                DontDestroyOnLoad(obj);
            }
            return _Instance;
        }
    }

    #endregion

    /// <summary>
    /// 超时时间
    /// 20秒
    /// </summary>
    private const float Time_Out = 20;

    /// <summary>
    /// 启动成功回调
    /// </summary>
    public event UnityAction<LocationInfo> SuccessCallback;

    /// <summary>
    /// 失败回调
    /// </summary>
    public event UnityAction<string> FailureCallback;

    /// <summary>
    /// 刷新回调
    /// </summary>
    public event UnityAction<LocationInfo> UpdateCallback;

    /// <summary>
    /// 停止回调
    /// </summary>
    public event UnityAction StoppedCallback;

    /// <summary>
    /// 是否开始
    /// </summary>
    private bool _IsStarted = false;

    // Start is called before the first frame update
    void Start()
    {
    
    

    }

    // Update is called once per frame
    void Update()
    {
    
    
        if (Input.location.status == LocationServiceStatus.Running)
        {
    
    
            OnUpdate(Input.location.lastData);
        }
#if UNITY_ANDROID && !UNITY_EDITOR
        if (UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.FineLocation))
        {
    
    
            StartGPS();
        }
#endif
    }

    /// <summary>
    /// 申请权限
    /// </summary>
    public static void RequestPermission()
    {
    
    
#if UNITY_ANDROID && !UNITY_EDITOR
        string permission = UnityEngine.Android.Permission.FineLocation;
        if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
        {
    
    
            UnityEngine.Android.Permission.RequestUserPermission(permission);
        }
#endif
    }

    /// <summary>
    /// 初始化
    /// </summary>
    public void Init()
    {
    
    
        RequestPermission();
        StartGPS();
    }

    /// <summary>
    /// 开始定位
    /// </summary>
    private void StartGPS()
    {
    
    
        if (!Input.location.isEnabledByUser)
        {
    
    
            OnError("用户没有权限");
            return;
        }
        if (_IsStarted)
        {
    
    
            return;
        }
        _IsStarted = true;
        Input.location.Start();
        StartCoroutine(GetGPS());
    }
    private IEnumerator GetGPS()
    {
    
    
        float time = Time_Out;
        while (Input.location.status == LocationServiceStatus.Initializing && time > 0)
        {
    
    
            yield return new WaitForSeconds(1);
            time--;
        }

        if (time < 1)
        {
    
    
            OnError("Timed out");
            yield break;
        }

        if (Input.location.status == LocationServiceStatus.Failed)
        {
    
    
            OnError("Unable to determine device location");
            yield break;
        }
        else
        {
    
    
            OnStartSuccess(Input.location.lastData);
        }
    }

    /// <summary>
    /// 停止定位
    /// </summary>
    public static void StopGPS()
    {
    
    
        if (!_Instance)
        {
    
    
            return;
        }
        if (!_Instance._IsStarted)
        {
    
    
            return;
        }
        try
        {
    
    
            Input.location.Stop();
            _Instance._IsStarted = false;
        }
        catch (System.Exception)
        {
    
    
            throw;
        }
        finally
        {
    
    
            _Instance.OnStopped();
        }
    }

    /// <summary>
    /// 启动成功
    /// </summary>
    /// <param name="locationInfo"></param>
    private void OnStartSuccess(LocationInfo locationInfo)
    {
    
    
        Debug.Log("OnStartSuccess:" + locationInfo.latitude + " " + locationInfo.longitude + " " + locationInfo.altitude + " " + locationInfo.horizontalAccuracy + " " + locationInfo.timestamp);
        SuccessCallback?.Invoke(locationInfo);
    }

    /// <summary>
    /// 发生错误
    /// </summary>
    private void OnError(string errorInfo)
    {
    
    
        Debug.Log("OnError:" + errorInfo);
        FailureCallback?.Invoke(errorInfo);
        StopGPS();
    }

    /// <summary>
    /// 更新位置
    /// </summary>
    /// <param name="locationInfo"></param>
    private void OnUpdate(LocationInfo locationInfo)
    {
    
    
        UpdateCallback?.Invoke(locationInfo);
    }

    /// <summary>
    /// 停止
    /// </summary>
    private void OnStopped()
    {
    
    
        Debug.Log("OnStopped:");
        StoppedCallback?.Invoke();

        if (gameObject)
        {
    
    
            Destroy(gameObject);
            _Instance = null;
        }
    }
}

Obtain the corresponding country and city according to GPS information

Basically all maps have this function, such as Baidu Maps, Google Maps, etc.

Baidu Maps: reverse geocoding rgc reverse geo retrieval | Baidu Maps API SDK (baidu.com)

Google Maps: Reverse Geocoding (Address Lookup) Request and Response | Geocoding API | Google Developers

The short answer is to send GPS information and self-created keys to the background through network requests, and the background returns the corresponding country and city information, which can be parsed according to the specified format, so I won’t introduce too much here.

But it is not easy to use, after all, it is not easy for people to count so much map information.

epilogue

If there is something wrong with the writing, you are welcome to criticize and correct me.

Guess you like

Origin blog.csdn.net/yr1102358773/article/details/128949452