六边形消除后填充逻辑实现求助:二维数组坐标更新
实现六边形下落填充的核心思路(数组优先更新)
我明白你的需求:销毁指定坐标的六边形后,让同一列上方的六边形“下落”填补空位,顶部生成新六边形,核心是更新二维数组Hexagons的引用,而非实际移动对象,确保每个坐标位置仅有唯一引用。下面是具体的实现方案,结合你的现有代码修改:
1. 调整销毁逻辑:记录要销毁的坐标而非对象
首先,把原来收集待销毁对象的逻辑改成记录待销毁的坐标,这样后续处理数组时更清晰,还能避免重复操作:
// 替换原来的HexToBeDestroyed对象列表,改用坐标列表存储要销毁的位置 List<Vector2Int> coordsToDestroy = new List<Vector2Int>(); // 在你的匹配逻辑中,添加坐标而非对象 if (MatchedColors == 2) { // 添加匹配的三个坐标 coordsToDestroy.Add(new Vector2Int(x, y)); coordsToDestroy.Add(new Vector2Int(x - 1, y)); coordsToDestroy.Add(new Vector2Int(x - 1, y - 1)); // 去重,避免重复添加同一坐标 coordsToDestroy = coordsToDestroy.Distinct().ToList(); } MatchedColors = 0;
2. 核心:处理下落填充与数组更新
编写专门的方法处理每一列的六边形下落和数组更新,核心是先收集每一列中保留的六边形,再重新填充数组,顶部空位生成新六边形:
private void HandleHexagonFall(int gridWidth, int gridHeight) { // 遍历每一列 for (int x = 0; x < gridWidth; x++) { // 收集当前列中未被标记销毁的有效六边形 List<HexCoordinates> validHexes = new List<HexCoordinates>(); for (int y = 0; y < gridHeight; y++) { Vector2Int currentCoord = new Vector2Int(x, y); // 如果当前坐标不在销毁列表,且对象存在 if (!coordsToDestroy.Contains(currentCoord) && Hexagons[x, y] != null) { validHexes.Add(Hexagons[x, y]); } } // 重新填充当前列的数组 for (int y = 0; y < gridHeight; y++) { if (y < validHexes.Count) { // 将保留的六边形放到新的坐标位置 Hexagons[x, y] = validHexes[y]; // 更新六边形自身的坐标记录(必须同步,否则后续匹配逻辑出错) Hexagons[x, y].Coordinates = new Vector2Int(x, y); // 更新世界位置,视觉上呈现下落效果 Hexagons[x, y].transform.position = CalcWorldPos(new Vector2(x, y)); // 更新对象名称以便调试 Hexagons[x, y].transform.name = $"X: {x} | Y: {y}"; } else { // 顶部空位生成新的六边形 GameObject newHex = Instantiate(HexagonPre, Vector2.zero, Quaternion.identity, HexGrid); // 随机设置颜色(复用你原来的逻辑) int randColor = Random.Range(0, 5); switch(randColor) { case 0: newHex.GetComponent<SpriteRenderer>().color = Color.blue; break; case 1: newHex.GetComponent<SpriteRenderer>().color = Color.red; break; case 2: newHex.GetComponent<SpriteRenderer>().color = Color.green; break; case 3: newHex.GetComponent<SpriteRenderer>().color = Color.yellow; break; case 4: newHex.GetComponent<SpriteRenderer>().color = Color.cyan; break; } // 设置新六边形的坐标信息 HexCoordinates hexCoord = newHex.GetComponent<HexCoordinates>(); hexCoord.Coordinates = new Vector2Int(x, y); newHex.transform.position = CalcWorldPos(new Vector2(x, y)); newHex.transform.name = $"X: {x} | Y: {y}"; // 将新六边形加入数组 Hexagons[x, y] = hexCoord; } } } // 最后销毁所有标记要删除的对象 foreach (Vector2Int coord in coordsToDestroy) { if (Hexagons[coord.x, coord.y] != null) { Destroy(Hexagons[coord.x, coord.y].gameObject); } } // 清空销毁列表,准备下一次操作 coordsToDestroy.Clear(); }
3. 补充初始化逻辑(关键!)
你的CreateGrid方法里缺少对Hexagons数组的赋值,必须补上,否则后续数组操作会报错:
public void CreateGrid(int gridWidth, int gridHeight) { // 初始化二维数组 Hexagons = new HexCoordinates[gridWidth, gridHeight]; for (int y = 0; y < gridHeight; y++) { for (int x = 0; x < gridWidth; x++) { GameObject Hexagon = Instantiate(HexagonPre, Vector2.zero, Quaternion.identity, HexGrid); int RandColor = Random.Range(0, 5); if (RandColor == 0) { Hexagon.GetComponent<SpriteRenderer>().color = Color.blue; } else if (RandColor == 1) { Hexagon.GetComponent<SpriteRenderer>().color = Color.red; } else if (RandColor == 2) { Hexagon.GetComponent<SpriteRenderer>().color = Color.green; } else if (RandColor == 3) { Hexagon.GetComponent<SpriteRenderer>().color = Color.yellow; } else if (RandColor == 4) { Hexagon.GetComponent<SpriteRenderer>().color = Color.cyan; } Vector2 gridPos = new Vector2(x, y); Hexagon.transform.position = CalcWorldPos(gridPos); HexCoordinates hexCoord = Hexagon.GetComponent<HexCoordinates>(); hexCoord.Coordinates = new Vector2Int(x, y); Hexagon.transform.name = "X: " + x + " | Y: " + y; // 将六边形引用存入数组 Hexagons[x, y] = hexCoord; } } }
核心原理说明
- 数组优先:我们通过重新填充数组来实现“下落”逻辑,确保每个坐标位置只有唯一的六边形引用,完全符合你的核心要求。
- 视觉同步:虽然没有移动对象,但通过
CalcWorldPos重新计算世界位置,让对象看起来是从上方下落到底部空位的。 - 数据一致性:每个六边形的
Coordinates组件必须和数组中的坐标严格对应,否则后续的匹配、销毁逻辑会出现错误。
内容的提问来源于stack exchange,提问作者FaTaLL
相关产品推荐
相关产品推荐

