You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 00:54:54