找回密码
 立即注册
查看: 209|回复: 0

Unity的Physics.Raycast()方法,为什么指定层遮罩后还会 ...

[复制链接]
发表于 2022-8-30 10:13 | 显示全部楼层 |阅读模式
错误代码

public class ChoiceWeapon : MonoBehaviour
{
    Ray ray;
    private void Update()
    {
        //从摄像机到鼠标指向位置发射射线
        Vector2 mousePos = Input.mousePosition;
        ray = Camera.main.ScreenPointToRay(mousePos);
        TestRay();
    }
    private void TestRay()
    {
        RaycastHit hitInfo;
        //下面的if,判断射线是否检测碰撞到Enemy层;
        if(Physics.Raycast(ray, out hitInfo, LayerMask.GetMask("Enemy")))
        {
            Debug.Log(hitInfo.transform.name);
        }
    }
}
上述代码,妄想通过射线,检测是否碰撞Enemy层的物体,然而在实际运行过程中,会发现射线碰撞所有物体的时候,都会执行if内的代码,即使不是Enemy层,也会被检测到。
  不使用GetMask()方法,用左移运算符也是如此;
if(Physics.Raycast(ray, out hitInfo,1<<2))
  且当第三个参数值较小的时候,无法检测到任何层的物体。
原因

  通过检查Raycast()方法的重载可以发现,并没有bool Physics.Raycast(Ray ray,out RaycastHit hitInfo, int layerMask)的重载。
  只有以下两种重载形式:




  当我们使用Physics.Raycast(ray,out hitInfo, LayerMask.GetMask("Enemy"))时,其实加载的是上面的那个重载,只有三个参数的重载。
  而LayerMask.GetMask("Enemy"))被当做了maxDistance,这里有些人可能会疑惑,简单解释一下,层是用int的不同位来表示的。


  如上图,Default就是1,TransparentFX就是1<<1,IgnoreRaycast就是1<<2,依此类推,Enemy就是1<<6。
  LayerMask.GetMask("Enemy")等价于1<<6;
  所以此时第三个参数是int类型,并没有报错。我们使用的层遮罩,就被当成了一个射线的最远距离,这也是为什么,当层遮罩的值很小时,无法检测到任何物体,因为指定的射线最远距离太短了,碰不到任何物体。
解决方案

  而我们想要使用层遮罩的话,就要使用下面这个重载。


  同时指定最远距离和层遮罩。
改动后的if代码:
        if(Physics.Raycast(ray, out hitInfo, Mathf.Infinity, LayerMask.GetMask("Enemy")))
        {
            //......
        }
Mathf.Infinity是正无穷大。
改完后,就可以正常的检测碰撞Enemy层物体了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 01:18 , Processed in 0.091380 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表