2017-01-16 10 views
3

У меня есть GameObject, который реализует IDragHandler и IDropHandler из UnityEngine.EventSystems.Unity Physics.Raycast, похоже, не правильно обнаруживает объект, который он ударил

В OnDrop, я хочу проверить, был ли этот объект удалено перед другим объектом. Я использую Physics.Raycast, но в некоторых случаях он возвращает true. Я использую экранную точку для луча как направление для своего луча, и это преобразование как источник для луча Raycast.

Мой код:

public void OnDrop(PointerEventData eventData) 
{ 
     var screenRay = Camera.main.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, 0.0f)); 
     var thisToObjectBehind = new Ray(transform.position, screenRay.direction); 
     Debug.DrawRay(thisToObjectBehind.origin, thisToObjectBehind.direction, Color.yellow, 20.0f, false); 
     RaycastHit hit; 
     if (Physics.Raycast(thisToObjectBehind, out hit)) 
     { 
      Debug.LogFormat("Dropped in front of {0}!", hit.transform); 
     } 
} 

Я использую перспективную камеру. Когда объект падает перед объектами прямо из экрана/камеры, Physics.Raycast иногда возвращает true, но «hit» содержит это, а не объект позади этого. Иногда он возвращает false. Ни один из этих двух результатов не ожидается, есть объекты позади этого, которые должны быть доступны Raycast.

Когда объект падает в передних объектах на окраине камеры, Physics.Raycast успешно находит объекты позади.

Отладочный луч выглядит хорошо, он нарисован из объекта, который я уронил, назад к объекту, который он должен ударить.

+0

Примечание: Если я вместо использования screenRay устанавливаю thisToObjectBehind = новый Ray (transform.position, transform.forward * -1), Raycast преуспевает, поэтому не должно быть ничего плохого с коллайдерами. Тем не менее, я не хочу ограничивать себя тем, что нужно смотреть в камеру. – Helena

+0

Каково значение eventData при успешном завершении и неудаче? – Bijan

+0

Вам не нужна LayerMask? – Maakep

ответ

1

Временное размещение объекта, сброшенного в слое IgnoreRaycast, решило мою проблему. Это также означало, что я мог бы пропустить, чтобы установить начало луча в transform.position.

public void OnDrop(PointerEventData eventData) 
    { 
     // Save the current layer the dropped object is in, 
     // and then temporarily place the object in the IgnoreRaycast layer to avoid hitting self with Raycast. 
     int oldLayer = gameObject.layer; 
     gameObject.layer = 2; 

     var screenRay = Camera.main.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, 0.0f)); 
     RaycastHit hit; 
     if (Physics.Raycast(screenRay, out hit)) 
     { 
      Debug.LogFormat("Dropped in front of {0}!", hit.transform); 
     } 

     // Reset the object's layer to the layer it was in before the drop. 
     gameObject.layer = oldLayer; 
    } 

EDIT: Удалены фрагменты try/finally из фрагмента кода из-за ошибок.

+0

Не поймайте исключения из API Unity. Делайте это только с помощью C# IO. Вам необязательно делать ваш код медленным в зависимости от того, сколько GameObjects вы привязали к этому коду. Просто выполните нулевую проверку. – Programmer

+0

Попробуйте, наконец, без улова, так же плохо? Я просто хотел удостовериться, что независимо от того, что происходит, я перемещаю игровой объект обратно на слой, который был заблаговременно, чтобы избежать странных поведений после того, как это вызвано. – Helena

+0

[JIT не выполняет оптимизацию на блоках «защищенных»/«попыток»] (http://stackoverflow.com/a/1350299/3785314) – Programmer