Unity中Physics.Raycast始终返回false问题求助
问题:Physics.Raycast始终返回false
你当前的代码存在多处核心逻辑错误,即使对象挂载了碰撞体也会导致射线检测完全失效:
核心错误原因
- Raycast参数传参完全错误:
Physics.Raycast的第二个参数要求传入世界空间下的射线方向向量,你直接传入了target.transform.position(目标的世界坐标点)。这个参数只有当射线起点cannon.position刚好在世界原点(0,0,0)时方向才会正确,只要cannon不在世界原点,射线方向会完全偏移,根本不可能指向目标。 - 层掩码定义了但未生效:你声明了
layerMask变量,但是调用Physics.Raycast时没有传入这个参数,层过滤逻辑完全不生效。另外你当前的掩码逻辑是忽略第8层所有碰撞体,需要确认第8层不是玩家/敌人所在的层,否则会直接过滤掉检测目标。 - 自身碰撞体干扰:如果作为射线起点的
cannon位置在自身挂载的BoxCollider/MeshCollider包围盒内部,射线发射后第一个命中的会是自己的碰撞体,无法检测到远处目标。 - 碰撞体配置异常:
- 如果碰撞体勾选了
Is Trigger,默认情况下射线不会检测触发器碰撞体 - 非凸的MeshCollider和非运动学Rigidbody搭配时碰撞检测会失效
- Physics面板的层碰撞矩阵如果取消了对应层的碰撞勾选,射线也会忽略对应层的碰撞体
- 如果碰撞体勾选了
- 调试逻辑错误:你只在射线命中时才绘制Debug线,根本看不到射线实际的发射方向,无法定位偏移问题。
修复方案
- 修正射线方向计算:方向必须是从起点指向目标的向量,即
target.transform.position - cannon.position,同时传入你定义的range作为射线最大距离,避免不必要的远距离检测。 - 把
layerMask传入Raycast参数,确认层逻辑正确:如果要忽略自身碰撞体,把自身对象放到单独的层,在掩码中排除该层即可。 - 调整cannon的位置,把它挪到自身碰撞体的包围盒外侧,避免射线起点埋在自身碰撞体里。
- 检查碰撞体配置:取消不必要的
Is Trigger勾选,非运动学刚体挂载的MeshCollider必须勾选Convex,确认Physics面板中对应层的碰撞检测是开启状态。 - 调整调试逻辑,不管射线是否命中都绘制调试线,方便在Scene窗口观察射线方向。
修正后的核心代码参考
void FixedUpdate() { if(gameObject.GetComponent<EnemyController>()){ checkIfTurn = gameObject.GetComponent<EnemyController>().isTurn; }else if(gameObject.GetComponent<PlayerController>()){ checkIfTurn = gameObject.GetComponent<PlayerController>().isTurn; } // 计算正确的射线方向:起点指向目标 Vector3 rayDir = (target.transform.position - cannon.position).normalized; // 传入方向、距离、层掩码,指定检测触发器规则 bool isHit = Physics.Raycast(cannon.position, rayDir, out hit, range, layerMask, QueryTriggerInteraction.UseGlobal); // 调试线:命中就画到命中点,没命中就画到最大射程位置 Debug.DrawLine(cannon.position, isHit ? hit.point : cannon.position + rayDir * range, isHit ? Color.red : Color.white, 2.5f); if (isHit){ Debug.Log("Hit tag " + hit.collider.tag + " Target Tag " + target.tag + " Has Shoot " + hasShoot + " is my turn " + checkIfTurn); if( hit.collider.tag == target.tag && !hasShoot && checkIfTurn ) { clone = Instantiate(bullet, cannon.position, gameObject.transform.rotation); clone.transform.SetParent(gameObject.transform); hasShoot = true; } } }
注意:如果你的第8层是玩家/敌人所在层,把
layerMask = ~layerMask这行逻辑删掉,或者把自身对象放到IgnoreRaycast层,避免过滤掉检测目标。
内容的提问来源于stack exchange,提问作者Jorge Criado ros
相关产品推荐
相关产品推荐

