【日志】unity俄罗斯方块(二)——方块碰撞检测

Bug修复日志

项目场景

在生成一个方块并解决边界限制以后,在方块与方块之间的碰撞检测出现了粗心的问题。


问题描述

在测试方块与方块之间的碰撞检测时,发现部分方块的碰撞检测不河狸。如下图所示:

原先的边界检测又又又失效了!!!

图中的绿色本该为J型方块,但是T型方块仍然能穿过该方块。

相关代码

    // 检查方块是否可以移动
    private bool IsCanMove()
    {
        // 检查是否超出边界
        for (int i = 0; i < transform.childCount - 2; i++)
        {
            int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);
            int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);
            if (roundY < 0 || roundX < 0 || roundX >= 10)
            {
                return false;
            }
            // 检查是否与其他方块重叠
            if (Board.grid[roundX, roundY] != null)
            {
                return false;
            }
        }
        return true;
    }

原因分析

通过多次Debug调试发现预制体下的第四个方块可以超出原先的设置的值,说明在遍历这些方块的时候遗漏了一个方块没有遍历。


解决方案

在每次遍历的时候重新调整遍历的范围,先前遍历的范围是 

for (int i = 0; i < transform.childCount - 2; i++)

因为我除了把四个方块放进了一个预制体中还把围绕旋转的对象也放入其中,所以应该是-1,减去一个多余子节点才对。

 // 检查方块是否可以移动
    private bool IsCanMove()
    {
        // 检查是否超出边界
        for (int i = 0; i < transform.childCount - 1; i++)
        {
        }
    }

今日收获 

停止状态

其实在停止下落的时候,打算通过切换状态来停止该方块,同时实现把方块信息放入场景中,方便后续执行检查并消除该行的方块。但是,因为我把整个状态用Enum存储,并在Update()里面调用,这导致一旦停留在Stop阶段,Update()会一直调用相关代码。

            transform.position += Vector3.down;
            if (!IsCanMove())
            {
                transform.position -= Vector3.down;
                moveType = MoveType.Stop;
            }

虽然不懂有没有其他的解决思路,但是让Update()停下来是我最先想到的,后来也是找到了解决方案:enabled = false;  直接让脚本失效就好了,这样就不会影响后续的操作。

    // 方块停止
    private void Stop()
    {
        isCanMove = false;
        // Debug.Log("Stop");
        for (int i = 0; i < transform.childCount - 1; i++)
        {
            int roundX = Mathf.RoundToInt(transform.GetChild(i).position.x);
            int roundY = Mathf.RoundToInt(transform.GetChild(i).position.y);
            // 添加方块到Board中
            Board.Instance.AddBlock(roundX, roundY, transform.GetChild(i));
        }

        // 检查游戏是否结束Debug.Log("检查游戏是否结束!");
        Board.Instance.IsGameOver(transform);

        // 消除行Debug.Log("检查是否消除行!");
        Board.Instance.CheckLine();

        // 生成新方块
        Board.Instance.SpawnBlock();

        enabled = false;
    }

添加相关对象

在把方块添加到场景里时,其实可以设置一个Transform的二维数组,为了防止超出数组范围而导致报错,索性给 height 扩大一些,确保有充足的空间。

    public static Transform[,] grid = new Transform[width, height + 5];
    // 添加方块
    public void AddBlock(int x, int y, Transform block)
    {
        grid[x, y] = block.transform;
    }

消除相关对象

在方块被放入grid以后,开始检查是否满行,如果满行就消除该行,并且下移所有方块。

    // 检查是否有可以消除的行
    public void CheckLine()
    {
        for (int i = height - 1; i >= 0; i--)
        {
            if (IsLineFull(i))
            {
                RemoveLine(i);
            }
        }
    }

    // 检查行是否满
    private bool IsLineFull(int y)
    {
        for (int i = 0; i < width; i++)
        {
            if (grid[i, y] == null)
            {
                return false;
            }
        }
        return true;
    }

    // 消除方块
    public void RemoveLine(int x)
    {
        for (int i = 0; i < width; i++)
        {
            Destroy(grid[i, x].gameObject);
            grid[i, x] = null;
        }
        MoveBlockdown(x);
    }

    // 下移方块
    public void MoveBlockdown(int h)
    {
        for (int i = h; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                if (grid[j, i] != null)
                {
                    grid[j, i - 1] = grid[j, i];
                    grid[j, i] = null;
                    grid[j, i - 1].position += Vector3.down;
                }
            }
        }
    }

碎碎念 

这个俄罗斯方块的核心逻辑到今天也算是写完了,后续打算完善该项目,继续深入搞点个人单机框架。

(也许吧,感觉燃尽了,因为又不干游戏开发,这项技能学习成本又很高,往后做基本没有回报,至于什么抖音微信小游戏,一没有美术,二自然流恰不了多少钱,这几天感觉纯粹就是失业在家心血来潮。)

今天看了《少年正义联盟》发现里面的战争世界挺有趣的,至少把一整颗小行星改造成一个武器,与这个类似的还有赛罗奥特曼的电影超银河传说(也忘记是不是这个名字了),里面贝利亚也有一艘战舰,类似用于挖掘型行星上面的矿产资源。Hello Megan!突然有点想法……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值