如何修改Unity代码以检测竖列中3个及以上的蓝色立方体
方块匹配检测代码优化(红块水平/蓝块垂直匹配)
现有Unity代码已实现横排3个及以上相邻红色立方体的检测,但蓝色立方体的竖列匹配检测尚未完善。游戏设定如下:
- 游戏区域:5格宽,10-15格高,方块类似俄罗斯方块从顶部下落
- 红色方块:仅支持水平匹配,当前逻辑正常
- 蓝色方块:仅支持垂直匹配,需解决非蓝色方块遮挡时的连续堆叠检测问题
原代码
using UnityEngine; using System.Collections.Generic; public class ColorMatcher : MonoBehaviour { public ScoreManager scoreManager; public LayerMask cubeLayer; public string cubeColor; public int detectedRedCubesLayer; // Layer for detected red cubes public int detectedBlueCubesLayer; public List<GameObject> detectedRedMatches = new List<GameObject>(); // List to store detected cubes public List<GameObject> detectedBlueMatches = new List<GameObject>(); public List<List<GameObject>> detectedMatches; public Vector2 rayDirection; public Vector2 rayOrigin; public bool matchDetected; public void Start() { rayOrigin.x = this.gameObject.transform.position.x; rayOrigin.y = this.gameObject.transform.position.y; } private void Update() { CheckForMatches(); } private void CheckForMatches() { if (cubeColor == "Red") { if (matchDetected == false) { CheckHorizontalMatches(cubeColor); } else { DisableCubeMatches(cubeColor); } } if(cubeColor == "Blue") { CheckVerticalMatches(cubeColor); DisableCubeMatches(cubeColor); } } private void CheckHorizontalMatches(string color) { Debug.DrawRay(transform.position, rayDirection, Color.red); for (int row = 0; row < 5; row++) { if (matchDetected == true) continue; // Perform the match checking var matches = CheckMatches(rayOrigin, color, rayDirection); if (matches.Count > 0) { Debug.Log($"Found at least one match in row {row}!"); matchDetected = true; } foreach (var matchList in matches) { // Add each matched GameObject to the detectedRedMatches list detectedRedMatches.AddRange(matchList); } } } private void CheckVerticalMatches(string color) { Debug.DrawRay(transform.position, rayDirection, Color.blue); } private void DisableCubeMatches(string cubecolor) { if (cubecolor == "Red") { // Implement logic for disabling consecutive red cubes } else if (cubecolor == "Blue") { // Implement logic for disabling consecutive blue cubes } } private List<List<GameObject>> CheckMatches(Vector2 rayOrigin, string color,Vector2 rayDirection) { // shoots a ray through all objects - results are ordered by distance from origin var hits = Physics2D.RaycastAll(rayOrigin, rayDirection, Mathf.Infinity, cubeLayer); var matches = new List<List<GameObject>>(4); // There are maximum 4 matches in a column of 15 items var currentMatch = new List<GameObject>(15); // maximum match size would be 15 if an entire column is blue e.g. for (var i = 0; i < hits.Length; i++) { // Have we hit something we are looking for? if (hits[i].transform.CompareTag(color)) { // simply track it in the current match list currentMatch.Add(hits[i].transform.gameObject); } else // we did hit something we are NOT looking for { // Does the currentMatch already contain enough items? if (currentMatch.Count >= 3) { // if so we add a new match to the results and start a potential new one matches.Add(currentMatch); currentMatch = new List<GameObject>(15); } else { // otherwise for a bit of memory saving we reuse the existing match // but erase it to also start a new one as it didn't reach the required amount of items currentMatch.Clear(); } } } return matches; } }
优化后的代码实现
重点完善CheckVerticalMatches方法,并调整蓝色方块的检测逻辑,确保能正确识别竖列中被遮挡但连续的蓝色方块:
using UnityEngine; using System.Collections.Generic; public class ColorMatcher : MonoBehaviour { public ScoreManager scoreManager; public LayerMask cubeLayer; public string cubeColor; public int detectedRedCubesLayer; // Layer for detected red cubes public int detectedBlueCubesLayer; public List<GameObject> detectedRedMatches = new List<GameObject>(); // List to store detected cubes public List<GameObject> detectedBlueMatches = new List<GameObject>(); public Vector2 horizontalRayDir; // 水平射线方向(左右) public Vector2 verticalRayDir; // 垂直射线方向(向下) public Vector2 gridTopLeft; // 游戏区域左上角坐标,需在Inspector中设置 public float cubeSize; // 单个方块的尺寸,需在Inspector中设置 public bool matchDetected; public void Start() { // 初始化射线方向 horizontalRayDir = Vector2.right; verticalRayDir = Vector2.down; } private void Update() { CheckForMatches(); } private void CheckForMatches() { if (cubeColor == "Red") { if (!matchDetected) { CheckHorizontalMatches(cubeColor); } else { DisableCubeMatches(cubeColor); } } if (cubeColor == "Blue") { if (!matchDetected) { CheckVerticalMatches(cubeColor); } else { DisableCubeMatches(cubeColor); } } } private void CheckHorizontalMatches(string color) { detectedRedMatches.Clear(); matchDetected = false; // 遍历每一行(取最大15行覆盖所有高度) for (int row = 0; row < 15; row++) { // 计算当前行的射线起点(从该行最左侧开始) Vector2 rayOrigin = new Vector2(gridTopLeft.x, gridTopLeft.y - row * cubeSize); Debug.DrawRay(rayOrigin, horizontalRayDir * 5 * cubeSize, Color.red); // 检测当前行的匹配 var matches = CheckMatches(rayOrigin, color, horizontalRayDir, 5 * cubeSize); if (matches.Count > 0) { matchDetected = true; foreach (var matchList in matches) { detectedRedMatches.AddRange(matchList); // 将匹配的方块标记到对应层 foreach (var cube in matchList) { cube.layer = detectedRedCubesLayer; } } } } } private void CheckVerticalMatches(string color) { detectedBlueMatches.Clear(); matchDetected = false; // 遍历每一列(共5列) for (int col = 0; col < 5; col++) { // 计算当前列的射线起点(从该列最顶部开始) Vector2 rayOrigin = new Vector2(gridTopLeft.x + col * cubeSize, gridTopLeft.y); Debug.DrawRay(rayOrigin, verticalRayDir * 15 * cubeSize, Color.blue); // 检测当前列的匹配 var matches = CheckMatches(rayOrigin, color, verticalRayDir, 15 * cubeSize); if (matches.Count > 0) { matchDetected = true; foreach (var matchList in matches) { detectedBlueMatches.AddRange(matchList); // 将匹配的方块标记到对应层 foreach (var cube in matchList) { cube.layer = detectedBlueCubesLayer; } } } } } private void DisableCubeMatches(string cubecolor) { if (cubecolor == "Red") { // 销毁匹配的红色方块并更新分数 foreach (var cube in detectedRedMatches) { Destroy(cube); } scoreManager.AddScore(detectedRedMatches.Count * 10); matchDetected = false; } else if (cubecolor == "Blue") { // 销毁匹配的蓝色方块并更新分数 foreach (var cube in detectedBlueMatches) { Destroy(cube); } scoreManager.AddScore(detectedBlueMatches.Count * 10); matchDetected = false; } } private List<List<GameObject>> CheckMatches(Vector2 rayOrigin, string color, Vector2 rayDirection, float rayLength) { // 发射射线,覆盖整个行/列的长度 var hits = Physics2D.RaycastAll(rayOrigin, rayDirection, rayLength, cubeLayer); // 按距离排序,确保从起点到终点的顺序正确 System.Array.Sort(hits, (a, b) => a.distance.CompareTo(b.distance)); var matches = new List<List<GameObject>>(); var currentMatch = new List<GameObject>(); foreach (var hit in hits) { if (hit.transform.CompareTag(color)) { currentMatch.Add(hit.transform.gameObject); } else { // 当前匹配序列长度达标则加入结果 if (currentMatch.Count >= 3) { matches.Add(new List<GameObject>(currentMatch)); } currentMatch.Clear(); } } // 检查最后一组匹配是否达标 if (currentMatch.Count >= 3) { matches.Add(new List<GameObject>(currentMatch)); } return matches; } }
关键修改说明
- 新增
gridTopLeft和cubeSize变量,用于准确定位每一行/列的射线起点,确保覆盖整个游戏区域 - 拆分水平/垂直射线方向,避免逻辑混淆
- 完善
CheckVerticalMatches:遍历5列,从每列顶部向下发射射线,利用CheckMatches检测连续蓝色方块 - 优化
CheckMatches:对射线检测结果按距离排序,确保顺序正确;处理最后一组可能的匹配 - 补充
DisableCubeMatches的实际逻辑,包括销毁方块和分数更新 - 蓝色方块的检测逻辑与红色对齐,先检测匹配再执行消除,避免重复操作
内容的提问来源于stack exchange,提问作者Placido Penitente
相关产品推荐
相关产品推荐

