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

Unity 2D游戏碰撞检测无响应问题排查求助

Unity 2D碰撞检测失效问题排查与解决思路

问题描述

  • 开发2D游戏时,OnCollisionEnter2D和OnTriggerEnter2D均无法触发碰撞检测
  • 70×70尺寸的小Collider完全处于10倍大的Collider中心时,无任何碰撞反馈,且小Collider无其他可碰撞对象
  • 仅保留基础形状的测试场景中,问题依旧存在
  • 期望检测玩家发射的hole对象与blue对象的碰撞并加分,但调试日志无相关输出

代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class Chapter1Manager : MonoBehaviour
{
    public Image crosshair; // 瞄准准星
    public Image[] holes = new Image[10];   // 存储hole预制体的数组
    public Canvas canvas;  // 画布引用
    public int bullets = 10; // 可用子弹数
    public TextMeshProUGUI bulletsCount; // 显示子弹数的UI元素
    public Image blue; // 蓝色对象引用
    public int points = 0; // 玩家得分
    public TextMeshProUGUI pointsText; // 显示得分的UI元素
    public int toSend = 0; // 跟踪下一个要发射的hole索引

    void Start()
    {
        // 初始化子弹数显示
        bulletsCount.text = bullets.ToString();

        // 查找所有带有"hole"标签的GameObject并存储到数组中
        GameObject[] foundHoles = GameObject.FindGameObjectsWithTag("hole");
        Debug.Log("找到 " + foundHoles.Length + " 个hole。");

        // 将找到的hole对象赋值给holes数组
        for (int i = 0; i < foundHoles.Length && i < holes.Length; i++)
        {
            holes[i] = foundHoles[i].GetComponent<Image>();
            Debug.Log("已赋值hole: " + holes[i].gameObject.name);
        }
    }

    void Update()
    {
        // 更新得分显示
        pointsText.text = "得分: " + points.ToString();

        // 检查是否还有剩余子弹
        if (bullets > 0)
        {
            // 检测空格键按下以发射
            if (Input.GetKeyDown(KeyCode.Space))
            {
                // 确保还有可发射的hole
                if (toSend < holes.Length) // 检查toSend是否在范围内
                {
                    // 将当前hole的位置设置为准星位置
                    holes[toSend].gameObject.transform.position = crosshair.transform.position;

                    // 递增下一个hole的索引并减少子弹数
                    toSend++;
                    bullets--;
                    bulletsCount.text = bullets.ToString(); // 更新子弹数显示
                    Debug.Log("已发射!剩余子弹: " + bullets);
                }
                else
                {
                    Debug.Log("没有更多hole可以发射了。");
                }
            }
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        // 记录碰撞对象的名称
        Debug.Log("检测到碰撞对象: " + collision.gameObject.name);

        // 检查碰撞对象是否是最后发射的hole或blue对象
        if (toSend > 0 && (collision.gameObject == holes[toSend - 1].gameObject || collision.gameObject == blue.gameObject))
        {
            points += 10; // 成功命中加分
            Debug.Log("命中!得分: " + points);
        }
    }
}

对象组件设置

Blue对象

  • Rigidbody2D:类型设为Dynamic,重力缩放0,未勾选固定角度
  • BoxCollider2D:尺寸适配对象,未勾选Is Trigger

Hole对象

  • Rigidbody2D:类型设为Dynamic,重力缩放0,未勾选固定角度
  • BoxCollider2D:尺寸70×70,未勾选Is Trigger

解决步骤

  1. 修正脚本挂载位置
    OnCollisionEnter2D方法仅会在挂载到同时带有Collider2D和Rigidbody2D组件的对象上时触发。当前Chapter1Manager脚本挂载的对象缺少这两个组件,要么将脚本挂载到blue或hole对象上,要么给挂载脚本的对象添加必要组件。

  2. 验证碰撞检测条件
    Unity 2D碰撞要求:

    • 两个对象中至少一个是Dynamic类型的Rigidbody2D(Static或Kinematic对象无法主动触发碰撞)
    • 若使用OnCollisionEnter2D,两个对象的Collider2D都不能勾选Is Trigger;若使用OnTriggerEnter2D,至少一个对象的Collider2D要勾选Is Trigger,且双方Rigidbody设置符合要求。
  3. 检查层碰撞矩阵
    打开Edit → Project Settings → Physics 2D,确认blue和hole所在的层在碰撞矩阵中被设置为互相允许碰撞。

  4. 替换瞬移为物理引擎驱动的移动
    代码中直接用transform.position设置hole位置属于瞬移,会跳过物理碰撞检测。改用Rigidbody2D的MovePosition方法:

    // 替换原位置设置代码
    Rigidbody2D holeRb = holes[toSend].gameObject.GetComponent<Rigidbody2D>();
    holeRb.MovePosition(crosshair.transform.position);
    
  5. 优化碰撞检测逻辑
    建议给每个hole对象单独挂载碰撞检测脚本,避免索引逻辑错误:

    // 挂载到hole对象的脚本
    public class HoleCollision : MonoBehaviour
    {
        private Chapter1Manager manager;
    
        void Start()
        {
            manager = FindObjectOfType<Chapter1Manager>();
        }
    
        private void OnCollisionEnter2D(Collision2D collision)
        {
            if (collision.gameObject.CompareTag("Blue")) // 给blue对象添加"Blue"标签
            {
                manager.points += 10;
                Debug.Log("命中!得分: " + manager.points);
            }
        }
    }
    
  6. 调试辅助技巧

    • 开启Unity场景视图的Gizmos,勾选Collider和Rigidbody,直观查看Collider的实际范围是否与视觉一致
    • 在Physics 2D设置中开启Debug模式,实时查看碰撞检测状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:29:59