基于高德地图 瓦片 实现 unity lbs

这篇具有很好参考价值的文章主要介绍了基于高德地图 瓦片 实现 unity lbs。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考文章:

 

        1.国内主要地图瓦片坐标系定义及计算原理 | CntChen Blog

        2.Unity LBS地图(瓦片地图,不接入任何SDK)_099_F11的博客-CSDN博客_unity离线地图

瓦片:高德等地图厂商把 世界地图分成了 好多张图片,每张图片就是一个瓦片

实现思路,根据 https 连接 请求对应 经纬度的瓦片,然后把他们拼接起来

代码实现:此代码只是一个demo,只有平移,没有缩放(效果太差)

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class Location
{
    public static LatLng mLatLng = null;

    public static IEnumerator SetMap(int x,int y, Image image,int zoom)
    {
        string _path = string.Format("http://webrd01.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=8", x, y, zoom);

        //string.Format("http://online1.map.bdimg.com/onlinelabel/?qt=tile&x={0}&y={1}&z=18", x, y);
        //string.Format("https://wprd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={0}&y={1}&z=16&scl=1&ltype=1", x, y);

        WWW www = new WWW(_path);
        while (!www.isDone)
        {
            yield return null;
        }
        image.sprite = Sprite.Create(www.texture, new Rect(0, 0, LocationMap.TileWidthAndHeigth, LocationMap.TileWidthAndHeigth), new Vector2(0.5f, 0.5f));//www.texture;SpriteRenderer.sprite.pivot
    }

    public static IEnumerator InitLocationPos()
    {
#if !UNITY_EDITOR
        if (!Input.location.isEnabledByUser)
        {
            Debug.LogError("Location is not enabled");
            yield break;
        }
#endif
        Input.location.Start(1,1);
        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)
        {
            yield break;
        }
        else
        {
            mLatLng = new LatLng(Input.location.lastData.longitude, Input.location.lastData.latitude);
            Input.location.Stop();
        }
    }

    /// <summary>
    /// 将tile(瓦片)坐标系转换为LatLngt(地理)坐标系,pixelX,pixelY为图片偏移像素坐标
    /// </summary>
    /// <param name="tileX"></param>
    /// <param name="tileY"></param>
    /// <param name="zoom"></param>
    /// <param name="pixelX"></param>
    /// <param name="pixelY"></param>
    /// <returns></returns>
    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 / LocationMap.TileWidthAndHeigth;
        double lng = (tileX + pixelXToTileAddition) / size * 360.0 - 180.0;

        double pixelYToTileAddition = pixelY / LocationMap.TileWidthAndHeigth;
        double lat = Math.Atan(Math.Sinh(Math.PI * (1 - 2 * (tileY + pixelYToTileAddition) / size))) * 180.0 / Math.PI;
        return new LatLng(lng, lat);
    }
    /// <summary>
    /// 将LatLngt地理坐标系转换为tile瓦片坐标系,pixelX,pixelY为图片偏移像素坐标
    /// </summary>
    /// <param name="latlng"></param>
    /// <param name="zoom"></param>
    /// <param name="tileX"></param>
    /// <param name="tileY"></param>
    /// <param name="pixelX"></param>
    /// <param name="pixelY"></param>
    public static TileInfo LatLngToTileXY(LatLng latlng, int zoom)
    {
        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;

        int tileX = (int)x;
        int tileY = (int)y;
        return new TileInfo(tileX, tileY, (int)((x - tileX) * LocationMap.TileWidthAndHeigth), (int)((y - tileY) * LocationMap.TileWidthAndHeigth));
    }
}

public class LatLng
{
    public double Longitude;
    public double Latitude;
    public LatLng(double longitude, double latitude)
    {
        Longitude = longitude;
        Latitude = latitude;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 滑动方向枚举
/// </summary>
public enum Direction
{
    up,
    down,
    left,
    right
}

/// <summary>
/// 瓦片信息类
/// </summary>
public class TileInfo
{
    public int TileX { get;  set; }
    public int TileY { get;  set; }
    public int PixelX { get;  set; }
    public int PixelY { get;  set; }

    public TileInfo(int tileX, int tileY, int pixelX, int pixelY)
    {
        TileX = tileX;
        TileY = tileY;
        PixelX = pixelX;
        PixelY = pixelY;
    }
}

public class TileImageInfo
{
    public int TileX { get; set; }
    public int TileY { get; set; }
    public GameObject Go { get; set; }

    public TileImageInfo(int tileX, int tileY,GameObject go)
    {
        TileX = tileX;
        TileY = tileY;
        Go = go;
    }
}

/// <summary>
/// 此类中 有两个坐标系,
/// 一个是瓦片地图 的坐标
/// 一个是实例化prefab 把瓦片地图 负值的gameobject 坐标
/// </summary>
public class LocationMap : MonoBehaviour
{
    //为什么设置成256*256,因为高的返回的图就是256的,还有一种类型是512*512
    public static float TileWidthAndHeigth = 256;
    public int TileZoom = 16;

    //加载的Image 的缩放
    public static float TileScale = 1;

    [SerializeField]
    private GameObject TileMap;

    private List<TileImageInfo> TileMaps = null;

    //中心 瓦片信息类
    private TileInfo m_centerTileInfo = null;

    //最好是正方形,容易计算,目前没处理 非正方形
    //瓦片行数
    public readonly int TileRow = 7;
    //瓦片列数
    public readonly int TileColumn = 5;

    private void Awake()
    {
        TileScale = TileMap.transform.localScale.x;
    }

    private void Start()
    {
        StartCoroutine(InitTileInfo());
    }

    private IEnumerator InitTileInfo()
    {
        yield return Location.InitLocationPos();

        if (Location.mLatLng != null)
        {
            LatLng latLng = Location.mLatLng;
#if UNITY_EDITOR
            //测试数据
            latLng = new LatLng(116.483988, 39.990255);
#endif
            if (latLng == null) yield break;

            m_centerTileInfo = Location.LatLngToTileXY(latLng, TileZoom);
            
            InitAllTile();
        }
    }

    private void InitAllTile()
    {
        //求的 左上角的 x 和 y的 瓦片值
        int x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
        int y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
        //左上角Image 图片的坐标
        Vector3 sour = new Vector3(0 - TileWidthAndHeigth * (TileColumn - 1)/2 * TileScale, 0 + TileWidthAndHeigth * (TileRow - 1)/2 * TileScale, 0);
        TileMaps = new List<TileImageInfo>(TileRow * TileColumn);
        TileImageInfo[] gameObjects = new TileImageInfo[TileRow * TileColumn];
        for (int i = 0; i < TileRow; i++)
        {
            for (int j = 0; j < TileColumn; j++)
            {
                GameObject g = Instantiate(TileMap, transform);
                g.transform.localPosition = sour + new Vector3(j * TileWidthAndHeigth * TileScale, 0, 0);

                //求取瓦片地图横向坐标
                int _x = x + j;

                //加载瓦片地图
                StartCoroutine(Location.SetMap(_x, y, g.GetComponent<Image>(), TileZoom));

                //瓦片Image 存入数组
                gameObjects[j + i * TileColumn] = new TileImageInfo(_x, y, g);
                g.SetActive(true);
            }
            //
            y += 1;
            //
            sour -= new Vector3(0, TileWidthAndHeigth * TileScale, 0);
        }
        TileMaps.AddRange(gameObjects);
    }

    /// <summary>
    /// 更新瓦片位置
    /// </summary>
    /// <param name="direction"></param>
    public void MapUpdate(Direction direction = Direction.up)
    {
        int x;
        int y;

        switch (direction)
        {
            case Direction.up:
                //下向上更新
                x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
                y = m_centerTileInfo.TileY - (TileRow - 1) / 2 - 1;
                for (int i = 0; i < TileColumn; i++)
                {
                    //把最后一排搬到第一排
                    TileImageInfo info = TileMaps[i + TileColumn * (TileRow - 1)];
                    info.Go.transform.localPosition += new Vector3(0, TileWidthAndHeigth * TileRow * TileScale, 0);
                    info.TileX = x;
                    info.TileX = y;

                    StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
                    x++;
                    //冒泡
                    for (int j = 1; j <= TileRow - 1; j++)
                    {
                        int index1 = i + TileColumn * (TileRow - j);
                        int index2 = i + TileColumn * (TileRow - j - 1);
                        TileImageInfo temp = TileMaps[index1];
                        TileMaps[index1] = TileMaps[index2];
                        TileMaps[index2] = temp;
                    }
                }
                m_centerTileInfo.TileY--;
                break;
            case Direction.down:
                x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
                y = m_centerTileInfo.TileY + (TileRow - 1) / 2 + 1;
                for (int i = 0; i < TileColumn; i++)
                {
                    //把第一排搬到最后一排
                    TileImageInfo info = TileMaps[i];
                    info.Go.transform.localPosition -= new Vector3(0, TileWidthAndHeigth * TileRow * TileScale, 0);
                    info.TileX = x;
                    info.TileX = y;

                    StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
                    x++;
                    //冒泡
                    for (int j = 0; j < TileRow - 1; j++)
                    {
                        int index1 = i + TileColumn * j;
                        int index2 = i + TileColumn * (j + 1);
                        TileImageInfo temp = TileMaps[index1];
                        TileMaps[index1] = TileMaps[index2];
                        TileMaps[index2] = temp;
                    }
                }
                m_centerTileInfo.TileY++;
                break;
            case Direction.left:
                x = m_centerTileInfo.TileX - (TileColumn - 1) / 2 - 1;
                y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
                for (int i = 0; i < TileRow; i++)
                {
                    //把最右列移到最左列
                    TileImageInfo info = TileMaps[i * TileColumn + (TileColumn - 1)];
                    info.Go.transform.localPosition -= new Vector3(TileWidthAndHeigth * TileColumn * TileScale, 0, 0);
                    info.TileX = x;
                    info.TileX = y;

                    StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
                    y++;
                    //冒泡
                    for (int j = 1; j <= TileColumn - 1; j++)
                    {
                        int index1 = i * TileColumn + (TileColumn - j);
                        int index2 = i * TileColumn + (TileColumn - j - 1);
                        TileImageInfo temp = TileMaps[index1];
                        TileMaps[index1] = TileMaps[index2];
                        TileMaps[index2] = temp;
                    }
                }
                m_centerTileInfo.TileX--;
                break;
            case Direction.right:
                x = m_centerTileInfo.TileX + (TileColumn - 1) / 2 + 1;
                y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
                for (int i = 0; i < TileRow; i++)
                {
                    //把最左列移到最右列
                    TileImageInfo info = TileMaps[i * TileColumn];
                    info.Go.transform.localPosition += new Vector3(TileWidthAndHeigth * TileColumn * TileScale, 0, 0);
                    info.TileX = x;
                    info.TileX = y;

                    StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
                    y++;
                    //冒泡
                    for (int j = 0; j < TileColumn - 1; j++)
                    {
                        int index1 = i * TileColumn + j;
                        int index2 = i * TileColumn + (j + 1);
                        TileImageInfo temp = TileMaps[index1];
                        TileMaps[index1] = TileMaps[index2];
                        TileMaps[index2] = temp;
                    }
                }
                m_centerTileInfo.TileX++;
                break;
        }

        //每次修改 释放资源
        Resources.UnloadUnusedAssets();
    }
}
using UnityEngine;
using UnityEngine.EventSystems;

public class MapPosManager : MonoBehaviour,IDragHandler,IBeginDragHandler,IEndDragHandler
{
    [SerializeField]
    private GameObject Map;

    //上次拖拽的位置
    Vector2 DragPos;
    private bool isDrag = false;

    //更新 地图的 位置边界
    private float lx;
    private float rx;
    private float ty;
    private float by;

    //每次位置变化大小
    private float changeSzie;

    //是否移动
    private float DragFlag = 50f;

    //地图
    private LocationMap map;

    private void Start()
    {
        map = Map.GetComponent<LocationMap>();

        changeSzie = LocationMap.TileWidthAndHeigth * LocationMap.TileScale;

        //初始化 边界
        lx = changeSzie;
        rx = -changeSzie;
        ty = -changeSzie;
        by = changeSzie;

    }

    void Update()
    {
        //注意 没有滑动时 不计算
        if (!isDrag) return;

        if (Map.transform.localPosition.x > lx)
        {
            map.MapUpdate(Direction.left);
            lx += changeSzie;
            rx += changeSzie;
        }
        if (Map.transform.localPosition.x < rx)
        {
            map.MapUpdate(Direction.right);
            rx -= changeSzie;
            lx -= changeSzie;
        }
        if (Map.transform.localPosition.y < ty)
        {
            map.MapUpdate(Direction.up);
            ty -= changeSzie;
            by -= changeSzie;

        }
        if (Map.transform.localPosition.y > by)
        {
            map.MapUpdate(Direction.down);
            by += changeSzie;
            ty += changeSzie;
        }
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        DragPos = eventData.position;
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (Input.touchCount == 2) return;

        Vector2 offset = (eventData.position - DragPos).normalized;
        Map.transform.position += new Vector3(offset.x, offset.y , 0) * DragFlag;
        DragPos = eventData.position;
        isDrag = true;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        isDrag = false;
    }
}

创建ui面板,挂上脚本, 其中tileMap 为Image

unity 接高德地图,Unity,unity,游戏引擎文章来源地址https://www.toymoban.com/news/detail-631528.html

到了这里,关于基于高德地图 瓦片 实现 unity lbs的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity 3D中使用tilemap创建关卡地图,瓦片间隙有漏缝

    我们使用一张图片来作为Sprite图集,创建地形图: 运行后,会发现,瓦片之间似乎总是有间距。 检查了图片发现,并不是图片边界存在间隙。 最后发现问题是出在图片资源中的线性过滤属性值: 在设计界面就能够看的很清楚。 起初还以为是tilemap的属性值设置不正确导致。

    2024年02月13日
    浏览(45)
  • unity游戏地图如何实现大世界地图

            大世界地图是游戏地图开发中不可或缺的场景,玩家可以在其中自由探索和移动。然而,实现大世界地图需要解决与大量地图数据处理和加载渲染优化有关的技术问题。本文将介绍如何利用unity游戏地图实现大世界地图。         地图数据处理是实现大世界地

    2024年02月06日
    浏览(45)
  • UE5、CesiumForUnreal接入XYZ格式地图瓦片如高德地图、OSM、ArcGIS等

    通过改造 cesium-native 和 cesiumforunreal 插件,参考 tms 的栅格地图瓦片加载逻辑,实现在UE5、CesiumForUnreal中接入 XYZ 格式的地图瓦片服务。 以高德XYZ格式地图加载为例,GIF动图如下: 首先对比 tms与xyz 瓦片的区别

    2024年02月13日
    浏览(50)
  • 手把手教你搭建个人地图服务器(高德离线部署解决方案):获取地图瓦片数据、高德JS API、私有化部署和调用。。。

    众所周知,目前常见的地图(高德、百度、腾讯等)只提供在线API服务,对于一些内网应用而言,如果需要使用地图展示,则由于不能访问互联网而无法使用类似的第三方地图服务。 本文,通过将高德地图瓦片数据 和 在线JS API做了本地部署,并修改API,将其所有的网络请求

    2024年02月04日
    浏览(59)
  • 瓦片地图编辑器——实现卡马克卷轴的编辑,键盘控制游戏移动和鼠标点击游戏编辑通过同一个视口实现。

      左边是游戏地图编辑区,右边是地图缓冲区,解决了地图缓冲区拖动bug,成功使得缓冲区可以更新。 AWSD进行移动 鼠标左右键分别是绘制/拖动 按F1健导出为mapv3.txt F2清空数组 打印的是游戏数组 easyx开发devcpp 5.11 easyx20220922版本

    2024年01月25日
    浏览(75)
  • 【实现100个unity游戏之20】制作一个2d开放世界游戏,TileMap+柏林噪声生成随机地图(附源码)

    我的上一篇文章介绍了TileMap的使用,主要是为我这篇做一个铺垫,看过上一篇文章的人,应该已经很好的理解TileMap的使用了,这里我就不需要过多的解释一些繁琐而基础的知识了,省去很多时间。所有没看过上一篇文章的小伙伴我强烈建议先去看看:

    2024年01月20日
    浏览(48)
  • 游戏开发之Unity2021智能导航地图烘焙

    单独调整移动某一颗树或者其它东西的时候可以按住 Ctrl+shift ,可以帮助我们自动吸附到某一个表面上  调出智能导航的面板,选择窗口,选择AI,选择导航 将地面设置为静态的,否则就不能进行烘焙,在导航中选择对象,选择可移动的 在导航中选择烘焙,选择bake  bake完之

    2024年02月10日
    浏览(47)
  • Unity2D绘制游戏地图

    首先,我们选择我们的地图素材(由于笔者在前段时间已经进行切割,最近才开始整理这一段,所以这个是用的老素材,可能有朋友就会觉得切割前后不一致,但是思路是一样的,大家学习思路即可)  接着,我们找到右上角的Slice进行图片切割,我这边简单介绍一下这个切

    2024年02月08日
    浏览(45)
  • 基于Unity+MySQL实现贪吃蛇小游戏

    【主界面控制程序】: using TMPro; using UnityEngine; using UnityEngine.UI; public class MainUIController : MonoBehaviour {     private static MainUIController _instance; //制作外部调用的方法     public static MainUIController Instance    //制作外部调用的方法     {                                        

    2023年04月15日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包