首页 > 解决方案 > b\w if(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 。这个问题让我很困惑。请帮忙详细解释一下。谢谢

标签: c#unity3d

解决方案


First of all: In your first snippet declaring RaycastHit hit; after already having Physics.Raycast(..., out hit) would be a compiler error ;)


Physics.Raycast returns a bool

True if the ray intersects with a Collider, otherwise false.

So execution wise of the Raycast itself No! There is no difference ... it is up to you whether you use return values of methods or not ...

BUT without the if check the value in hit might be incomplete/invalid/not set at all and you would get exceptions trying to go on ...

The clue here RaycastHit is a struct! So different to a class type it can not be null but always has some default values.

You can not check e.g.

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

So while some of the values might indicate it is invalid like hit.collider or hit.gameObject (basically all reference type properties) others again are structs or other value types themselves so they contain always a value .. which is not valid though like e.g. hit.point (would by default be Vector3.zero), hit.distance(would be default be 0f) etc (basically all value type properties).

Therefore to be sure you actually have hit something before using the values stored in hit you use the bool return value to check whether hit actually contains valid data or not.


Usually always when you use the out keyword you let your method return bool for indicating whether the out parameter was successfully filled or not.

As explanation let's just look at this example (maybe not the best but I couldn't come up with something more explanatory) using 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
}

Now ofcourse you could use something like

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

but it will always throw an exception!

Therefore you rather want to check whether it actually succeeded

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

Note btw that instead of

transform.TransformDirection(Vector3.forward)

you should rather simply use

transform.forward

推荐阅读