unity动态加载地图瓦片

效果如下:

以下为UI结构即具体设置:

PanelTest设置:

Center设置:

Scroll View设置:

Viewport设置:

Content设置:

ImageTempLate设置:

原理简图:

代码:

  1 using Common;
  2 using UnityEngine;
  3 using UnityEngine.UI;
  4 
  5 namespace Lugs
  6 {
  7     /// <summary>
  8     /// 图形切割配置
  9     /// </summary>
 10     public class GridData
 11     {
 12         /// <summary>
 13         /// 原始图片的文件
 14         /// </summary>
 15         public string SrcFileName = @"D:\0_lugsProjects\MapCutter\SourceMap.jpg";
 16         /// <summary>
 17         /// 切割后的图片输出目录
 18         /// </summary>
 19         public string OutDirectory = @"D:\0_lugsProjects\MapCutter\Res\";
 20         /// <summary>
 21         /// 图片宽度
 22         /// </summary>
 23         public int ImageWidth = 3000;
 24         /// <summary>
 25         /// 图片高度
 26         /// </summary>
 27         public int ImageHeight = 1900;
 28         /// <summary>
 29         /// 格子宽度
 30         /// </summary>
 31         public int GridWidth = 256;
 32         /// <summary>
 33         /// 格子高度
 34         /// </summary>
 35         public int GridHeight = 256;
 36         /// <summary>
 37         /// 切片文件前缀
 38         /// </summary>
 39         public string titlePrefixName = "WorldMap_";
 40         /// <summary>
 41         /// 切片文件扩展名
 42         /// </summary>
 43         public string expandedName = @".jpg";
 44     }
 45 
 46     /// <summary>
 47     /// UI显示的格子结构
 48     /// </summary>
 49     public class GridItem
 50     {
 51         public bool isUsed;
 52         public int index;
 53         public RawImage image;
 54 
 55         GridData data;
 56         public GridItem(RawImage itemTemplate, GridData data)
 57         {
 58             image = GameObject.Instantiate<RawImage>(itemTemplate, itemTemplate.transform.parent);
 59             image.enabled = true;
 60             image.gameObject.SetActive(true);
 61             this.data = data;
 62         }
 63 
 64         public void Clear()
 65         {
 66             isUsed = false;
 67             index = -1;
 68             image.enabled = false;
 69         }
 70 
 71         public void SetInfo(int index, int xGridCount)
 72         {
 73             this.index = index;
 74             isUsed = true;
 75             image.enabled = true;
 76             int x = index % xGridCount;
 77             int y = index / xGridCount;
 78             GameObject obj = image.gameObject;
 79             obj.name = string.Format("[{0},{1}]", x, y);
 80             int width = data.GridWidth;
 81             int height = data.GridHeight;
 82             obj.transform.localPosition = new Vector3(x * width, -y * height);
 83             if ((x + 1) * width > data.ImageWidth)
 84             {
 85                 width = data.ImageWidth - x * width;
 86             }
 87 
 88             if ((y + 1) * height > data.ImageHeight)
 89             {
 90                 height = data.ImageHeight - y * height;
 91             }
 92             image.rectTransform.sizeDelta = new Vector2(width, height);
 93             string imageName = "worldmap_" + (index + 1).ToString("D2");
 94             //Debug.Log("imageName = " + imageName);
 95             ImageAssetItem item = new ImageAssetItem(UIManager.Str_WorldMapTxFolderName, imageName, false, true);
 96             item.LoadImage(() =>
 97             {
 98                 image.texture = item.TexObject;
 99             });
100         }
101     }
102 }

UI代码:

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.UI;
  5 
  6 namespace Lugs
  7 {
  8     public sealed class PanelTest : MonoBehaviour
  9     {
 10         public RawImage RawImage_GridTemplate;
 11         public ScrollRect scrollRect;
 12         public Slider Slider_Scale;
 13         /// <summary>
 14         /// 视口的缩放系数,默认不缩放
 15         /// </summary>
 16         float mScreenRatio = 1.0f;
 17         public float ScreenRatio
 18         {
 19             get
 20             {
 21                 return mScreenRatio;
 22             }
 23             set
 24             {
 25                 mScreenRatio = value;
 26                 Vector2 pos = scrollRect.normalizedPosition;
 27                 pos.x = Mathf.Clamp01(pos.x);
 28                 pos.y = Mathf.Clamp01(pos.y);
 29                 scrollRect.normalizedPosition = pos;
 30             }
 31         }
 32         /// <summary>
 33         /// 可视区域的可滑动的区域大小
 34         /// </summary>
 35         Vector2 scrollRectMoveArea;
 36         /// <summary>
 37         /// 可视区域大小
 38         /// </summary>
 39         Vector2 screenSize;
 40         /// <summary>
 41         /// 扩展的可视区域大小
 42         /// </summary>
 43         Vector2 screenExtendSize;
 44         /// <summary>
 45         /// 可视区域左下角在可滑动区域内的位置
 46         /// </summary>
 47         Vector2 screenLBPosAtMoveArea;
 48         /// <summary>
 49         /// 可视区域右上角在可滑动区域内的位置
 50         /// </summary>
 51         Vector2 screenRTPosAtMoveArea;
 52         /// <summary>
 53         /// 扩展的可视区域左下角在可滑动区域内的位置
 54         /// </summary>
 55         Vector2 screenExtendLBPosAtMoveArea;
 56         /// <summary>
 57         /// 扩展的可视区域右上角在可滑动区域内的位置
 58         /// </summary>
 59         Vector2 screenExtendRTPosAtMoveArea;
 60         /// <summary>
 61         /// 实际可视区域的扩展比例
 62         /// </summary>
 63         float screenExtendRatio;
 64         /// <summary>
 65         /// 地图的尺寸
 66         /// </summary>
 67         Vector2 mapSize;
 68         /// <summary>
 69         /// 铅直方向上的格子数量
 70         /// </summary>
 71         int mYGridCount;
 72         /// <summary>
 73         /// 水平方向上的格子数量
 74         /// </summary>
 75         int mXGridCount;
 76         /// <summary>
 77         /// 格子出现的左下位置
 78         /// </summary>
 79         Vector2 gridLBPos;
 80         /// <summary>
 81         /// 格子出现的右上位置
 82         /// </summary>
 83         Vector2 gridRTPos;
 84         /// <summary>
 85         /// 使用中的UI格子
 86         /// </summary>
 87         List<GridItem> useGridList = new List<GridItem>();
 88         /// <summary>
 89         /// 未使用的UI格子
 90         /// </summary>
 91         List<GridItem> unUsedGridList = new List<GridItem>();
 92         /// <summary>
 93         /// 格子的配置数据
 94         /// </summary>
 95         GridData mGridData = new GridData();
 96         void Start()
 97         {
 98             Init();
 99             OnScrollValueChanged();
100         }
101 
102         void Init()
103         {
104             RawImage_GridTemplate.gameObject.SetActive(false);
105 
106             mXGridCount = Mathf.CeilToInt(mGridData.ImageWidth * 1.0f / mGridData.GridWidth);
107             mYGridCount = Mathf.CeilToInt(mGridData.ImageHeight * 1.0f / mGridData.GridHeight);
108 
109             mapSize = new Vector2(mGridData.ImageWidth, mGridData.ImageHeight);
110             screenSize = UIManager.Instance.UIUGUIRootScene.sizeDelta;
111             scrollRect.content.sizeDelta = mapSize;
112             scrollRectMoveArea = mapSize - screenSize;
113             screenExtendRatio = 0.1f;
114             screenExtendSize = screenSize * screenExtendRatio;
115             scrollRect.onValueChanged.RemoveAllListeners();
116             scrollRect.onValueChanged.AddListener(OnScrollValueChanged);
117         }
118         void OnScrollValueChanged(Vector2 vec2)
119         {
120             OnScrollValueChanged();
121         }
122 
123         void OnScrollValueChanged()
124         {
125             //ScrollRect当前在可是区域滑动的比例
126             float xPox = scrollRect.horizontalNormalizedPosition;
127             float yPos = scrollRect.verticalNormalizedPosition;
128 
129             //视口在可移动区域内的位置
130             screenLBPosAtMoveArea.x = scrollRectMoveArea.x * xPox;
131             screenLBPosAtMoveArea.y = scrollRectMoveArea.y * yPos;
132             screenRTPosAtMoveArea = screenLBPosAtMoveArea + screenSize;
133 
134             //扩展视口在可移动区域内的位置
135             screenExtendLBPosAtMoveArea = screenLBPosAtMoveArea - screenExtendSize;
136             screenExtendRTPosAtMoveArea = screenRTPosAtMoveArea + screenExtendSize;
137 
138             //计算格子出现的位置:左下 右上
139             gridLBPos.x = Mathf.FloorToInt(screenExtendLBPosAtMoveArea.x / mGridData.GridWidth);
140             gridLBPos.y = Mathf.FloorToInt(screenExtendLBPosAtMoveArea.y / mGridData.GridHeight);
141             gridRTPos.x = Mathf.CeilToInt(screenExtendRTPosAtMoveArea.x / mGridData.GridWidth);
142             gridRTPos.y = Mathf.CeilToInt(screenExtendRTPosAtMoveArea.y / mGridData.GridHeight);
143 
144             //分别计算左下格子和右上格子的索引
145             int iMin = (int)gridLBPos.x;
146             int iMax = (int)gridRTPos.x;
147             int jMin = (int)gridLBPos.y;
148             int jMax = (int)gridRTPos.y;
149 
150             //刷新格子
151             RefreshGrid(iMin, iMax, jMin, jMax);
152         }
153 
154         void RefreshGrid(int iMin, int iMax, int jMin, int jMax)
155         {
156             //先全部重置所有格子为 未使用
157             for (int i = 0; i < useGridList.Count; ++i)
158             {
159                 GridItem item = useGridList[i];
160                 item.isUsed = false;
161                 unUsedGridList.Add(item);
162             }
163 
164             //整个扩展可视区域内需要的格子数量
165             int needCount = 0;
166             for (int i = iMin; i <= iMax; ++i)
167             {
168                 for (int j = jMin; j <= jMax; ++j)
169                 {
170                     if (i < 0 || i >= mXGridCount || j < 0 || j >= mYGridCount)
171                     {
172                         continue;
173                     }
174 
175                     ++needCount;
176                     //格子在可移动区域的索引
177                     int index = (mYGridCount - j - 1) * mXGridCount + i;
178                     for (int k = 0; k < useGridList.Count; ++k)
179                     {
180                         GridItem item = useGridList[k];
181                         if (index == item.index)
182                         {
183                             unUsedGridList.Remove(item);
184                             item.isUsed = true;
185                             break;
186                         }
187                     }
188                 }
189             }
190 
191             //不够的话补够
192             for (int i = useGridList.Count; i < needCount; ++i)
193             {
194                 GridItem item = GetItem();
195                 useGridList.Add(item);
196             }
197 
198             //刷新格子的信息
199             bool isRightInfo = false;
200             GridItem firstFreeItem = null;
201             for (int i = iMin; i <= iMax; ++i)
202             {
203                 for (int j = jMin; j <= jMax; ++j)
204                 {
205                     if (i < 0 || i >= mXGridCount || j < 0 || j >= mYGridCount)
206                     {
207                         continue;
208                     }
209 
210                     isRightInfo = false;
211                     firstFreeItem = null;
212                     int index = (mYGridCount - j - 1) * mXGridCount + i;
213                     for (int k = 0; k < useGridList.Count; ++k)
214                     {
215                         GridItem item = useGridList[k];
216 
217                         if (null == firstFreeItem && !item.isUsed)
218                         {
219                             firstFreeItem = item;
220                         }
221 
222                         if (item.isUsed && (index == item.index))
223                         {
224                             isRightInfo = true;
225                             break;
226                         }
227                     }
228 
229                     if (!isRightInfo)
230                     {
231                         if (null != firstFreeItem)
232                         {
233                             firstFreeItem.SetInfo(index, mXGridCount);
234                         }
235                     }
236                 }
237             }
238         }
239 
240         GridItem GetItem()
241         {
242             for (int i = unUsedGridList.Count - 1; i >= 0;)
243             {
244                 GridItem tmpItem = unUsedGridList[i];
245                 tmpItem.Clear();
246                 unUsedGridList.Remove(tmpItem);
247                 return tmpItem;
248             }
249 
250             GridItem item = new GridItem(RawImage_GridTemplate, mGridData);
251             return item;
252         }
253 
254         public void OnSliderValueChange()
255         {
256             float scale = Slider_Scale.value / Slider_Scale.maxValue;
257             scrollRect.viewport.localScale = new Vector3(scale, scale, 1);
258             Rect baseRect = (scrollRect.transform as RectTransform).rect;
259             scrollRect.viewport.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, baseRect.width / scale);
260             scrollRect.viewport.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, baseRect.height / scale);
261             ScreenRatio = 1 / scale;
262         }
263     }
264 }

 

posted @ 2020-12-03 16:46  小·糊涂仙  阅读(2977)  评论(1编辑  收藏  举报