unity定位
前言
最近在做一款手游,然后策划给的需求就是定位到当前用户所在的城市,然后花了一个上午给做了出来,思路大概就是通过手机定位获取到当前位置的经度和纬度,然后通过各个地图(我这里用的是百度地图)给出的接口进行逆地理编码
经纬度
在unity中的Input类里面有location这个属性,这个属性返回一个LocationService类可以为我们做一些GPS定位的操作,而其中
的LocationInfo则是定位完成后返回的一些数据。unity官网链接:https://docs.unity3d.com/ScriptReference/LocationService.Start.html
LocationService类:
1.isenabledbyuser 用户是否开启了定位服务(好像没什么用,一直是true)
2.lastdata 最后一次获取到的位置信息
3.status 定位的服务状态
4.start 启动定位服务
5.stop 停止定位服务
LocationInfo 结构体:
(1) altitude – 海拔高度
(2) horizontalAccuracy – 水平精度
(3) latitude – 纬度
(4) longitude – 经度
(5) timestamp – 最近一次定位的时间戳,从1970开始
(6) verticalAccuracy – 垂直精度
这些属性,除了timestamp为double外, 其余全为 float 型。
参考链接:https://blog.csdn.net/Superficialtise/article/details/77443980
获取经纬度
/// <summary>
/// 打开定位服务并获取经纬度
/// </summary>
/// <returns></returns>
IEnumerator OpenGps()
{
if (!Input.location.isEnabledByUser)
{
debug.Log("未获取定位权限", null);
GpsFaile?.Invoke(FailCode.DontRoot);
GpsFaile = null;
yield break;
}
Input.location.Start(500, 500); //这里精度我设为了500
int maxSecend = 5; //5秒钟计时
WaitForSeconds wait = new WaitForSeconds(1);
while (Input.location.status == LocationServiceStatus.Initializing&&maxSecend>0)
{
yield return wait;
maxSecend--;
}
if (Input.location.status == LocationServiceStatus.Failed)
{
debug.Log("定位失败",null);
yield break;
}
//注意:这里不能直接访问 Input.location.lastData,检索通过Input.location.lastData,服务无法立即开始发送位置数据。代码应检查Input.location.status当前的服务状态
float latitude = Input.location.lastData.latitude; //经度
float longitude = Input.location.lastData.longitude;//纬度
Input.location.Stop();
}
这里需要注意的是Input.location.lastData 服务无法立即开始发送位置数据
百度地图
百度地图平台链接:http://lbsyun.baidu.com/products/products/location
百度地图逆地理编码链接:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding-abroad
首先需要注册并创建应用获取到appkey,然后在unity中请求返回信息,数据为json格式
/// <summary>
/// 从百度地图获取逆地理信息
/// </summary>
/// <returns></returns>
IEnumerator GetInfoFromBaidu(float latitude, float longitude)
{
//这里要注意在手机上请求http是不能获取结果的,所以这里用的是https
string baiduUrl= string.Format("https://api.map.baidu.com/reverse_geocoding/v3/?ak={0}&output=json&coordtype=wgs84ll&location={1},{2}", BaiduKey.appKey, latitude, longitude);
debug.Log("baiduUrl", baiduUrl);
UnityWebRequest webRequest = UnityWebRequest.Get(baiduUrl);
yield return webRequest.SendWebRequest();
int maxSecond = 20;
WaitForSeconds wait = new WaitForSeconds(1);
while (webRequest.isDone == false)
{
yield return wait;
maxSecond--;
}
if (maxSecond <= 0)
{
debug.Log("超时", null);
yield break;
}
if (webRequest.isDone&&string.IsNullOrEmpty(webRequest.error))
{
info = webRequest.downloadHandler.text;
yield break;
}
debug.Log("获取位置失败:", webRequest.error);
}
注意:这里请求网址的时候如果是在手机端则需要使用https请求,否则将获取不到结果
Sn校验码的问题
有时候返回sn校验码与服务端校验码不对的时候,在链接里加入sn校验码,sn校验码计算方式
/// <summary>
/// 百度地图sn校验码
/// </summary>
public class AKSNCaculater
{
private static string MD5(string password)
{
byte[] textBytes = System.Text.Encoding.UTF8.GetBytes(password);
try
{
System.Security.Cryptography.MD5CryptoServiceProvider cryptHandler;
cryptHandler = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hash = cryptHandler.ComputeHash(textBytes);
string ret = "";
foreach (byte a in hash)
{
ret += a.ToString("x");
}
return ret;
}
catch
{
throw;
}
}
private static string UrlEncode(string str)
{
str = System.Web.HttpUtility.UrlEncode(str);
byte[] buf = Encoding.ASCII.GetBytes(str);//等同于Encoding.ASCII.GetBytes(str)
for (int i = 0; i < buf.Length; i++)
if (buf[i] == '%')
{
if (buf[i + 1] >= 'a') buf[i + 1] -= 32;
if (buf[i + 2] >= 'a') buf[i + 2] -= 32;
i += 2;
}
return Encoding.ASCII.GetString(buf);//同上,等同于Encoding.ASCII.GetString(buf)
}
private static string HttpBuildQuery(IDictionary<string, string> querystring_arrays)
{
StringBuilder sb = new StringBuilder();
foreach (var item in querystring_arrays)
{
sb.Append(UrlEncode(item.Key));
sb.Append("=");
sb.Append(UrlEncode(item.Value));
sb.Append("&");
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
/// <summary>
/// 获取百度地图的校验码
/// </summary>
/// <param name="ak"></param>
/// <param name="sk"></param>
/// <param name="url"></param>
/// <param name="querystring_arrays"></param>
/// <returns></returns>
public static string CaculateAKSN(string ak, string sk, string url, IDictionary<string, string> querystring_arrays)
{
var queryString = HttpBuildQuery(querystring_arrays);
var str = UrlEncode(url + "?" + queryString + sk);
return MD5(str);
}
}