Любая разница ч / б если (Raycast ....) и Raycast в одиночку - PullRequest
0 голосов
/ 03 марта 2020

Есть ли разница между двумя кодами ниже:

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

Это не просто декларация, не так ли? Я знаю, если (sth) просто равно if (sth == true). Однако я не думаю, что это необходимо использовать, если здесь. Эта проблема меня сильно смущает. Пожалуйста, помогите с подробным объяснением. Спасибо

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Прежде всего: в вашем первом фрагменте объявления RaycastHit hit; после уже имеющегося Physics.Raycast(..., out hit) будет ошибка компилятора;)


Physics.Raycast возвращает bool

Истина, если луч пересекается с коллайдером, в противном случае - ложь.

Так что с точки зрения исполнения самого Raycast нет! Нет никакой разницы ... зависит от вас, используете ли вы возвращаемые значения методов или нет ...

НО без проверки if значения в hit может быть неполным / недействительным / не заданным вообще, и вы получите исключения, пытающиеся go на ...

Подсказка RaycastHit - это struct! Он отличается от class типа и не может быть null, но всегда имеет некоторые значения по умолчанию.

Вы не можете проверить, например,

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

Так что, хотя некоторые значения могут указывать, что он недействителен, как hit.collider или hit.gameObject (в основном все свойства ссылочного типа), другие снова являются структурами или сами другие типы значений, поэтому они всегда содержат значение .., которое недопустимо, хотя, например, hit.point (по умолчанию будет Vector3.zero), hit.distance (по умолчанию будет 0f) и c ( в основном все свойства типа значения).

Поэтому, чтобы убедиться, что вы действительно нажали что-то перед использованием значений, хранящихся в hit, вы используете возвращаемое значение bool, чтобы проверить, содержит ли hit действительные данные или not.


Обычно всегда, когда вы используете ключевое слово 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
1 голос
/ 03 марта 2020

Из Документы Unity :

publi c stati c bool Physics.Raycast (...) вернет true, если приведенный луч пересекает коллайдер.

Таким образом, внутренний блок в первой версии вашего кода:

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

будет выполняться только тогда, когда приведенный Луч попадет на коллайдер.

Вторая версия вашего кода будет всегда выполняются, так как условий раньше не было.

В любом случае Луч будет кастоваться в обоих случаях, если это было целью вашего вопроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...