如果(raycast..)和单独使用raycast,则有任何区别



以下两个代码之间有什么区别吗:

if(Physics.Raycast(transform.position , transform.TransformDirection(Vector3.forward), out hit)){
RaycastHit hit;
targetDistance = hit.distance;
Physics.Raycast(transform.position , transform.TransformDirection(Vector3.forward), out hit;
.........

这不仅仅是一个简单的声明,是吗?我知道if(sth(等于if(sth==true(。但是,我认为没有必要在这里使用if。这个问题让我很困惑。请帮助详细解释。谢谢

首先:在您的第一个代码段中,在已经有Physics.Raycast(..., out hit)之后声明RaycastHit hit;将是编译器错误;(


Physics.Raycast返回布尔

如果光线与碰撞器相交,则为True,否则为false。

所以Raycast本身的执行方式不!没有区别。。。是否使用方法的返回值取决于您。。。

但是如果没有if检查,hit中的值可能是不完整的/无效的/根本没有设置,并且您会遇到试图继续的异常。。。

这里的线索RaycastHit是一个struct!与class类型不同,它不能是null,但总是有一些默认值。

你不能检查,例如

Physics.Raycast(transform.position, transform.forward, out var hit);
if(hit != null) // not possible!
{
...
}

因此,虽然有些值可能表明它是无效的,比如hit.colliderhit.gameObject(基本上是所有引用类型属性(,但其他值本身也是结构或其他值类型,因此它们总是包含一个值。。这是无效的,尽管类似于例如hit.point(默认为Vector3.zero(、hit.distance(默认为0f(等(基本上所有值类型属性(。

因此,为了确保在使用存储在hit中的值之前确实命中了一些内容,您可以使用bool返回值来检查hit是否实际包含有效数据。


通常,当您使用out关键字时,您会让方法返回bool,以指示out参数是否已成功填充。

作为解释,让我们看看这个使用out:的例子(也许不是最好的,但我无法想出更具解释性的东西(

bool FindObject(string name, out GameObject obj)
{
if(string.isNullOrWhiteSpace(name))
{
obj = null;
return false;
}
obj = GameObject.Find(name);
return obj; // true if obj exists
}

当然,现在你可以使用类似的东西

FindObject("", out var obj);
obj.transform.position = Vector3.zero;

但它总是会抛出一个异常!

因此,你更想检查它是否真的成功了

if(FindObject("abc", out var obj)
{
obj.transform.position = Vector3.zero;
}

注意,不是

transform.TransformDirection(Vector3.forward)

你应该简单地使用

transform.forward

来自Unity文档:

如果投射的光线与对撞机相交,则Raycast(…(将返回true。

因此,您代码的第一个版本中的内部块:

if(Physics.Raycast(transform.position , transform.TransformDirection(Vector3.forward), out hit)){
RaycastHit hit;
targetDistance = hit.distance;
}

将仅在投射的光线击中碰撞器时执行。

代码的第二个版本将始终执行,因为之前没有任何条件。

不管怎样,如果这是你问题的焦点,那么在这两种情况下都会播放雷。

最新更新