Unity LBS地图(瓦片地图,不接入任何SDK)

来源:互联网 发布:depthmap软件 编辑:程序博客网 时间:2024/06/04 23:24

随着现象级手游“精灵宝可梦GO”的走红,许多手游都想接入LBS社交,基于地理位置交互的LBS功能。那么在Unity中怎么实现LBS地图呢,最简单的接入地图SDK,像百度地图、高德地图,一些常用到的功能都有了,像“阴阳师”的LBS就是接入的高德地图。但接入SDK的方式,有个麻烦的问题,须要针对Android各IOS分别接入,主要是接入后的功能玩法都要用Android的java和IOS的OC去实现,这样就要同时维护两份代码了,而且测试还得在手机上测,甚是麻烦,还可能有设备兼容问题。经过一番研究,发现了一种实现方法,瓦片地图,可直接在Unity中用C#实现,不限平台。




互联网地图服务商的在线地图都通过瓦片的方式提供,称为瓦片地图服务。最常见的地图瓦片是图片格式的,一般大小为256*256。瓦片地图就是把地图当作一张大图,在几个不同的缩放比例下,按大小固定切分为许多瓦片,这样每张瓦片图的经纬度就可以定位到了。如此,可根据给定的经纬度求得对应缩放比例下的瓦片,然后根据瓦片地图坐标x、y增减可求得周边的瓦片。那么一张瓦片图就可以用瓦片坐标x、y和缩放比例z确定了。例如百度地图http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=49310&y=10242&z=18,就是瓦片坐标x=49310,y=10242,在缩放比例为18的一张瓦片图了。


怎样根据经纬度算到对应的瓦片坐标呢?
//将tile(瓦片)坐标系转换为LatLngt(地理)坐标系,pixelX,pixelY为图片偏移像素坐标    public static LatLng TileXYToLatLng(int tileX, int tileY, int zoom, int pixelX = 0, int pixelY = 0)    {        double size = Math.Pow(2, zoom);        double pixelXToTileAddition = pixelX / 256.0;        double lng = (tileX + pixelXToTileAddition) / size * 360.0 - 180.0;        double pixelYToTileAddition = pixelY / 256.0;        double lat = Math.Atan(Math.Sinh(Math.PI * (1 - 2 * (tileY + pixelYToTileAddition) / size))) * 180.0 / Math.PI;        return new LatLng(lng, lat);    }


也可以根据瓦片坐标计算对应的经纬度
//将LatLngt地理坐标系转换为tile瓦片坐标系,pixelX,pixelY为图片偏移像素坐标    public static void LatLngToTileXY(LatLng latlng, int zoom, out int tileX, out int tileY, out int pixelX, out int pixelY)    {        double size = Math.Pow(2, zoom);        double x = ((latlng.Longitude + 180) / 360) * size;        double lat_rad = latlng.Latitude * Math.PI / 180;        double y = (1 - Math.Log(Math.Tan(lat_rad) + 1 / Math.Cos(lat_rad)) / Math.PI) / 2;        y = y * size;        tileX = (int)x;        tileY = (int)y;        pixelX = (int)((x - tileX) * 256);        pixelY = (int)((y - tileY) * 256);    }


如此这样,就可以把一张张瓦片图拼成地图了,仔细看下百度地图或高德地图,好像也是这样一张张小图加载来实现的。最简单的实现:先定位到自己的经纬度,求得对应缩放比例z下的瓦片坐标,加载对应的瓦片地图和周边的瓦片地图,拖动时再加载相邻的瓦片,缩放时,清除当前所有的图片,再求得中心点的瓦片坐标,这样就可以实现一个基本地图了。那么在unity中按这样实现就非常方便了,想在地图上加什么功能都非常方便,也不用考虑平台的问题。例如可以随意加上任何Marker。甚至用3D实现也不成问题。


另上Unity中定位代码

using UnityEngine;using System.Collections;public class Location : MonoBehaviour {    IEnumerator Start()    {        if (!Input.location.isEnabledByUser)        {            Debug.LogError("Location is not enabled");            yield break;        }        Input.location.Start();        int maxWait = 30;        while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)        {            yield return new WaitForSeconds(1);            maxWait--;        }        if (maxWait < 1)        {            Debug.LogError("Location time out");            yield break;        }        if (Input.location.status == LocationServiceStatus.Failed)        {            Debug.LogError("Unable to determine device location");            yield break;        }        else        {            LatLng latlng = new LatLng(Input.location.lastData.longitude, Input.location.lastData.latitude);            Debug.Log(latlng);        }        Input.location.Stop();    }}

参考文章:

http://www.jianshu.com/p/0b292688b6af


0 0
原创粉丝点击