我们在项目中常常会有点击屏幕中的物体后实现打开UI菜单、高亮等功能的需求,下面我盘点了两种常用的方法。

射线检测

  • 在任意进入场景会被加载的脚本,如玩家角色中的脚本中加入创建发射射线的函数(最好是单例的脚本,不然函数有可能会被多次执行)
    •     private RaycastHit CastRay()
          {
              Vector3 screenFar = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.farClipPlane);
              Vector3 screenNear = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane);
              Vector3 far = Camera.main.ScreenToWorldPoint(screenFar);
              Vector3 near = Camera.main.ScreenToWorldPoint(screenNear);
              RaycastHit hit;
              Physics.Raycast(near, far - near, out hit);
              return hit;
          }
      
    • screenFar和screenNear分别获取鼠标点击的xy坐标,以及MainCamera的最远剪切面和最近剪切面,不让射线无限延长
    • 使用ScreenToWorldPoint()将z轴(深度)的距离转换为场景空间的坐标点
    • Raycast()的参数分别为射线的起点,方向,碰撞物信息
  • 在Update()中编写以下代码,当用户按左键时,如果射线检测到了物体则返回else中的信息
    •     void Update ()
          {
              if (Input.GetMouseButtonDown(0))
              {
                  RaycastHit hit = CastRay();
                  if (!hit.collider)
                  {
                      return;
                  }
                  else
                  {
                      //测试,输出被交互的物体,可以再次编写其他逻辑
                      Debug.LogWarning("被射线检测的物体名:" + hit.collider.gameObject.name);
                  }
              }
          }   
      

OnMouseDown()

  • 在需要被交互的物体中加入collider
  • 在需要被交互的物体中编写脚本,脚本中加入函数OnMouseDown()编写交互后的逻辑
  • 当用户按左键时,如果左键指向绑定该脚本的物体则执行下面代码
    private void OnMouseDown()
    {
        //测试,输出被交互的物体,可以再次编写其他逻辑
        Debug.LogWarning("被射线检测的物体名:" + gameObject.name);
    }

参考资料

https://www.bilibili.com/video/BV1R3411W73E

https://docs.unity3d.com/cn/current/ScriptReference/MonoBehaviour.OnMouseDown.html