Unity技术求助:射线检测指定标签物体时准星显示异常
问题排查:准星显示/隐藏异常问题
我折腾了好几个小时,想实现这个功能:发射射线,当射线碰到带特定标签的物体时显示准星,没击中就隐藏准星。但实际效果不对,要么得先点击准星才显示,要么显示后没法隐藏。下面是我的交互脚本代码,帮忙看看问题出在哪。
public Collider clickObject; public Animator m_Animator; [SerializeField] public GameObject Crosshair; private Ray _ray; private RaycastHit _hit; private bool _opened; void Start() { m_Animator = gameObject.GetComponent<Animator>(); Crosshair.SetActive(false); } private void Update() { if (Input.GetKeyDown(KeyCode.Mouse0)) { Click(); } } private void Click() { if (!clickObject) return; if (!m_Animator) return; _ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(_ray, out _hit)) { if (_hit.collider.CompareTag("InteractObject")) { Crosshair.SetActive(true); } else { Crosshair.SetActive(false); } if (_hit.collider == clickObject) { if (_opened) { m_Animator.SetBool("isOpen", true); _opened = false; } else { m_Animator.SetBool("isOpen", false); _opened = true; } } } }
问题根源
- 准星逻辑仅在点击时触发:当前准星的显示/隐藏逻辑被放在
Click()方法中,只有点击鼠标左键时才会执行射线检测,无法实现实时检测的需求,导致准星不能随鼠标移动即时更新状态。 - 依赖多余的前置判断:
Click()方法开头的if (!clickObject) return;和if (!m_Animator) return;会导致如果这两个变量未赋值,准星逻辑完全无法执行,而准星控制其实不需要依赖这两个变量。 - 未处理射线未命中的情况:仅在射线命中物体时才修改准星状态,若射线未击中任何物体,准星会保持之前的状态,无法自动隐藏。
修复后的代码
public Collider clickObject; public Animator m_Animator; [SerializeField] public GameObject Crosshair; private Ray _ray; private RaycastHit _hit; private bool _opened; void Start() { m_Animator = gameObject.GetComponent<Animator>(); Crosshair.SetActive(false); } private void Update() { // 每帧实时检测射线,更新准星状态 _ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(_ray, out _hit)) { Crosshair.SetActive(_hit.collider.CompareTag("InteractObject")); } else { // 射线未命中任何物体时强制隐藏准星 Crosshair.SetActive(false); } // 独立处理点击交互逻辑 if (Input.GetKeyDown(KeyCode.Mouse0)) { Click(); } } private void Click() { if (!clickObject || !m_Animator) return; _ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(_ray, out _hit) && _hit.collider == clickObject) { _opened = !_opened; m_Animator.SetBool("isOpen", !_opened); } }
修复说明
- 准星逻辑移至Update:每帧执行射线检测,实现准星状态的实时更新,无需等待点击触发。
- 补充射线未命中处理:当射线未击中任何物体时,强制隐藏准星,避免状态残留。
- 分离准星与交互逻辑:准星控制不再依赖
clickObject和m_Animator,即使这两个变量未赋值,准星功能仍能正常工作。 - 简化交互逻辑:将开关状态切换简化为
_opened = !_opened,代码更简洁易读。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

