免下载,unity通过代码动态加载高德瓦片地图

项目需要加入瓦片地图,经过搜索,找到相关文章如下:

基于高德地图 瓦片 实现 unity lbs_unity 接高德地图_仑儿的博客-CSDN博客

这里再将代码和实现过程复刻一下:

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 = 9;

    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(120.37993, 36.11559);
#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 Camera cam;

    private void Start()
    {
        map = Map.GetComponent<LocationMap>();
        cam = Camera.main;
        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;
    }
}

项目设置:

1.新建一个image设置参数如下

 因为瓦片地图的常用分辨率为256*256.所以我们这里也设置为256.

2.新建canvas,panel,给panel挂载脚本

 给脚本赋值,tile zoom是瓦片地图的层级。

3.调整摄像机位置展示地图

扫描二维码关注公众号,回复: 17084208 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_29296473/article/details/131939431