1 private void ControlDisplayArea(Vector3 pos, bool IsInit) 2 { 3 4 IntVector2 newcoord = GetCoord(pos);//新得到的地图下标 5 if (IsInit)//如果为初始化显示 6 { 7 ControlDisplayAll(false); 8 int x_min = newcoord.x - area >= 0 ? newcoord.x - area : 0; 9 int y_min = newcoord.y - area >= 0 ? newcoord.y - area : 0; 10 int x_max = newcoord.x + area <= size_x - 1 ? newcoord.x + area : size_x - 1; 11 int y_max = newcoord.y + area <= size_z - 1 ? newcoord.y + area : size_z - 1; 12 for (int i = y_min; i <= y_max; i++) 13 for (int j = x_min; j <= x_max; j++) 14 { 15 if (GetOrder(j, i) != -1) 16 map.GetChild(GetOrder(j, i)).gameObject.SetActive(true); 17 } 18 return; 19 } 20 if (newcoord == oldcoord)//如果对象下标未更新 21 return; 22 int index;//计算下标的辅助变量 23 if (newcoord.x - oldcoord.x != 0)//左右方向更新 24 { 25 bool IsLeft = newcoord.x - oldcoord.x < 0 ? true : false; 26 27 for (int i = newcoord.y - area; i <= newcoord.y + area; i++)//生成按新坐标边界 28 { 29 index = GetOrder(IsLeft ? newcoord.x - area : newcoord.x + area, i); 30 if (index != -1) 31 map.GetChild(index).gameObject.SetActive(true); 32 } 33 for (int j = oldcoord.y - area; j <= oldcoord.y + area; j++)//消去按旧坐标边界 34 { 35 index = GetOrder(IsLeft ? oldcoord.x + area : oldcoord.x - area, j); 36 if (index != -1) 37 map.GetChild(index).gameObject.SetActive(false); 38 } 39 } 40 41 if (newcoord.y - oldcoord.y != 0)//上下方向更新 42 { 43 bool IsUp = newcoord.y - oldcoord.y > 0 ? true : false; 44 45 for (int i = newcoord.x - area; i <= newcoord.x + area; i++)//生成按新坐标边界 46 { 47 index = GetOrder(i, IsUp ? newcoord.y + area : newcoord.y - area); 48 if (index != -1) 49 map.GetChild(index).gameObject.SetActive(true); 50 } 51 for (int j = oldcoord.x - area; j <= oldcoord.x + area; j++) 52 { 53 index = GetOrder(j, IsUp ? oldcoord.y - area : oldcoord.y + area); 54 if (index != -1) 55 map.GetChild(index).gameObject.SetActive(false);//消去按旧坐标边界 56 } 57 } 58 oldcoord = newcoord; 59 }
新的方法的原理。每次对象坐标改变时,先记录下改变前其n圈内的格子坐标,然后算出改变后n圈内的格子坐标,后者全部setActive(true).后者减去前者作为显示对象。前者减去后者作为隐藏对象
1 using System.Collections; 2 using System.Collections.Generic; 3 using System.Linq; 4 using UnityEngine; 5 6 public class Control_Area : MonoBehaviour 7 { 8 9 public Transform mPlayer;//监控对象 10 public Transform mMap;//地图 11 public int mMaxRow;//最大行数 12 public int mMaxCol;//最大列数 13 public int mSize;//chunk尺寸,用来计算目标所在坐标 14 public int Area=3;//显示范围 15 //坐标类 16 17 private Coordinate CurCoord = new Coordinate(-99,-99); 18 private List<Coordinate> curCbs = null;//用来显示范围内的格子 19 private List<Coordinate> preCbs = null;//用来消去上次范围内但不在现范围内的格子 20 21 22 /// <summary> 23 /// 用来初始化参数 24 /// </summary> 25 /// <param name="max_row"></param> 26 /// <param name="max_col"></param> 27 /// <param name="size"></param> 28 /// <param name="map"></param> 29 /// <returns></returns> 30 public void Init(int max_row, int max_col,int size,Transform map) 31 { 32 mMaxRow = max_row; 33 mMaxCol = max_col; 34 mSize = size; 35 mMap = map; 36 } 37 38 public void Start() 39 { 40 //初始化时隐藏所有chunk 41 for (int i = 0; i < mMap.childCount; i++) 42 { 43 Transform tf = mMap.GetChild(i); 44 tf.gameObject.SetActive(false); 45 } 46 InvokeRepeating("ChunkPositionUpdate", 0f, 1f); 47 } 48 49 /// <summary> 50 /// 更新位置,允许超出范围 51 /// </summary> 52 /// <returns></returns> 53 public void ChunkPositionUpdate() 54 { 55 if (mPlayer == null || mMap == null) 56 { 57 return; 58 } 59 //将人物的世界坐标变换为地图的局部坐标 60 Vector3 localHeroPos = mMap.transform.InverseTransformPoint(mPlayer.transform.position); 61 62 int col = (int)(localHeroPos.x / mSize); 63 int row = (int)(localHeroPos.z / mSize); 64 65 //如果仍然处于旧位置 66 if (CurCoord.Row == row && CurCoord.Col == col) 67 { 68 return; 69 } 70 //先把旧的周围所有圈方块记录下来 71 preCbs = null; 72 curCbs = null; 73 preCbs = new List<Coordinate>(); 74 curCbs = new List<Coordinate>(); 75 for (int i = 0; i <Area; ++i) 76 { 77 preCbs.AddRange(new List<Coordinate>(GetCoordInR(CurCoord.Row, CurCoord.Col, i))); 78 } 79 80 CurCoord.Row = row; 81 CurCoord.Col = col; 82 ChunkVisibleUpdate(); 83 } 84 85 /// <summary> 86 /// 获取ChunkID 87 /// </summary> 88 /// <param name="row"></param> 89 /// <param name="col"></param> 90 /// <returns>int</returns> 91 public int GetChunkID(int row,int col) 92 { 93 return row * mMaxCol + col; 94 } 95 96 /// <summary> 97 /// 更新可见度 98 /// </summary> 99 /// <returns></returns> 100 public void ChunkVisibleUpdate() 101 { 102 for (int i = 0; i < Area; ++i) 103 { 104 Coordinate[] cbs = GetCoordInR(CurCoord.Row, CurCoord.Col, i); 105 curCbs.AddRange(new List<Coordinate>(cbs)); 106 } 107 List<Coordinate> display = new List<Coordinate>(curCbs.ToArray());//显示的新格子 108 List<Coordinate> hide = new List<Coordinate>(preCbs.ToArray());//消去的旧格子 109 for (int i = curCbs.Count-1; i >=0; i--) 110 { 111 for (int j = preCbs.Count-1; j>=0;j--) 112 { 113 if (Coordinate.Equal(curCbs[i],preCbs[j])) 114 { 115 display[i] = null; 116 hide[j] = null; 117 } 118 } 119 } 120 121 display.RemoveAll(item =>{ return item == null; });//消去为null的坐标,这里指新坐标和旧坐标公有的格子 122 hide.RemoveAll(item => { return item == null; }); 123 124 for (int i = 0; i < display.Count; ++i) 125 { 126 mMap.GetChild(GetChunkID(display[i].Row, display[i].Col)).gameObject.SetActive(true); 127 } 128 129 for (int i = 0; i < hide.Count; ++i) 130 { 131 mMap.GetChild(GetChunkID(hide[i].Row, hide[i].Col)).gameObject.SetActive(false); 132 } 133 134 } 135 136 137 /// <summary> 138 /// 返回地图范围内的坐标 139 /// </summary> 140 /// <param name="i"></param> 141 /// <param name="j"></param> 142 /// <returns>Coordinate</returns> 143 private Coordinate GetValidCoord(int i, int j) 144 { 145 if (i < 0 || i >= mMaxRow || j < 0 || j >= mMaxCol) 146 { 147 return null; 148 } 149 return new Coordinate(i,j); 150 } 151 152 153 154 /// <summary> 155 /// 返回返回指定第几围的坐标,若是超出范围则被排除在外 156 /// </summary> 157 /// <param name="row"></param> 158 /// <param name="col"></param> 159 /// <param name="r"></param> 160 /// <returns>Coordinate[]</returns> 161 private Coordinate[] GetCoordInR(int row, int col, int r) 162 { 163 List<Coordinate> list = new List<Coordinate>(); 164 for (int i = 0; i < 2 * r + 1; ++i) 165 { 166 Coordinate cb = GetValidCoord(row - r, col - r + i); 167 if (cb != null && !list.Contains(cb)) 168 { 169 list.Add(cb); 170 } 171 cb = GetValidCoord(row - r + i, col - r); 172 if (cb != null && !list.Contains(cb)) 173 { 174 list.Add(cb); 175 } 176 cb = GetValidCoord(row + r, col - r + i); 177 if (cb != null && !list.Contains(cb)) 178 { 179 list.Add(cb); 180 } 181 cb = GetValidCoord(row - r + i, col + r); 182 if (cb != null && !list.Contains(cb)) 183 { 184 list.Add(cb); 185 } 186 } 187 return list.ToArray(); 188 } 189 190 /// <summary> 191 /// 坐标类 192 /// </summary> 193 class Coordinate 194 { 195 public int Row; 196 public int Col; 197 public Coordinate(int row, int col) 198 { 199 Row = row; 200 Col = col; 201 } 202 public Coordinate(Coordinate m) 203 { 204 Row = m.Row; 205 Col = m.Col; 206 } 207 public static bool Equal(Coordinate a, Coordinate b) 208 { 209 if (a.Col == b.Col && a.Row == b.Row) 210 return true; 211 else 212 return false; 213 } 214 } 215 }