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

Unity中OnCollisionEnter2D多对象碰撞致剩余砖块计数错误求助

问题分析与修复方案

核心问题原因

  1. 初始计数不准确:动态生成砖块时,若remBricks初始值未正确统计普通砖块和特殊砖块的总数,会导致后续计数提前归0。
  2. 多球重复碰撞计数:当前仅靠单个球的hasCollided/hasCollidedBrick标记防止重复触发,但多球同时碰撞同一个砖块时,每个球的标记独立,仍会多次调用ScoreUp(5),导致remBricks被多次递减。
  3. 计数逻辑耦合错误:通过ScoreUp的参数val==5判断是否减砖块数,若后续有其他逻辑调用ScoreUp(5)(比如奖励分数),会误减砖块计数。

具体修复步骤

1. 修正初始砖块计数

在场景生成完成后,统一统计所有有效砖块数量,替换原有的初始赋值逻辑:

// 在SceneGenerator的生成代码末尾添加
GameManager.instance.remBricks = GameObject.FindGameObjectsWithTag("Brick").Length + GameObject.FindGameObjectsWithTag("SpecialBrick").Length;

或者在每生成一个砖块时同步递增计数:

// 生成普通砖块时
Instantiate(brickPrefab, position, rotation);
GameManager.instance.remBricks++;

// 生成特殊砖块时
Instantiate(specialBrickPrefab, position, rotation);
GameManager.instance.remBricks++;

2. 给砖块添加防重复销毁标记

新建BrickBase.cs脚本并挂载到所有砖块上,标记砖块是否已处理碰撞:

public class BrickBase : MonoBehaviour
{
    public bool isDestroyed = false;
}

修改Ball的碰撞逻辑,先检查砖块的标记:

private void OnCollisionEnter2D(Collision2D collision)
{
    var brickBase = collision.gameObject.GetComponent<BrickBase>();
    if (brickBase != null && brickBase.isDestroyed)
        return;

    if(collision.gameObject.tag == "Brick")
    {
        brickBase.isDestroyed = true;
        GameManager.instance.ScoreUp(5);
        GameManager.instance.DecreaseBrickCount();
        Destroy(collision.gameObject);
    }
    else if(collision.gameObject.tag == "SpecialBrick")
    {
        brickBase.isDestroyed = true;
        SceneGenerator.instance.remBalls++;
        GameManager.instance.ScoreUp(5);
        GameManager.instance.DecreaseBrickCount();
        Destroy(collision.gameObject);
        clone = Instantiate(gameObject, transform.position,transform.rotation);
    }
}

3. 拆分计数与加分逻辑

在GameManager中新增专门的砖块计数递减方法,避免和加分逻辑耦合:

public void ScoreUp(int val)
{
    score += val;
    textScore.text = score.ToString();
}

public void DecreaseBrickCount()
{
    remBricks--;
    // 确保计数不会小于0
    if(remBricks < 0) remBricks = 0;
    
    if (remBricks == 0)
    {
        winText.SetActive(true);
        textScore.gameObject.SetActive(false);
        isWin = true;
    }
}

4. 移除球的冗余标记(可选)

既然已经通过砖块的标记防止重复碰撞,可删除Ball中的LateUpdate方法以及hasCollided、hasCollidedBrick变量,简化代码。

额外注意事项

  • 确保所有砖块(普通/特殊)都挂载了BrickBase脚本,否则碰撞时会跳过计数。
  • 动态生成砖块时,务必同步更新remBricks,避免初始计数错误。

内容的提问来源于stack exchange,提问作者Rogmier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 18:35:23