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

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;
            }
        }
    }
}

问题根源

  1. 准星逻辑仅在点击时触发:当前准星的显示/隐藏逻辑被放在Click()方法中,只有点击鼠标左键时才会执行射线检测,无法实现实时检测的需求,导致准星不能随鼠标移动即时更新状态。
  2. 依赖多余的前置判断:Click()方法开头的if (!clickObject) return;和if (!m_Animator) return;会导致如果这两个变量未赋值,准星逻辑完全无法执行,而准星控制其实不需要依赖这两个变量。
  3. 未处理射线未命中的情况:仅在射线命中物体时才修改准星状态,若射线未击中任何物体,准星会保持之前的状态,无法自动隐藏。

修复后的代码

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);
    }
}

修复说明

  1. 准星逻辑移至Update:每帧执行射线检测,实现准星状态的实时更新,无需等待点击触发。
  2. 补充射线未命中处理:当射线未击中任何物体时,强制隐藏准星,避免状态残留。
  3. 分离准星与交互逻辑:准星控制不再依赖clickObject和m_Animator,即使这两个变量未赋值,准星功能仍能正常工作。
  4. 简化交互逻辑:将开关状态切换简化为_opened = !_opened,代码更简洁易读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:35:00