2017-01-16 5 views
3

UnityEngine.EventSystems에서 IDragHandler 및 IDropHandler를 구현하는 GameObject가 있습니다.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를 반환하지만 "적중"은 뒤에있는 객체가 아니라 이것을 포함합니다. 때로는 false를 반환합니다. 이 두 가지 결과 중 어느 것도 기대할 수는 없지만 Raycast에 가능해야하는 요소가 있습니다.

카메라 뷰의 외곽에있는 전면 객체에서 객체를 떨어 뜨리면 Physics.Raycast는 그 뒤에있는 객체를 찾는 데 성공합니다.

디버그 레이는 괜찮아 보이는 데요, 내가 떨어 뜨린 개체에서부터 끌어 내려야합니다.

+0

참고 : screenRay를 사용하는 대신 thisToObjectBehind = new Ray (transform.position, transform.forward * -1)를 설정하면 Raycast가 성공하므로 colliders에 문제가 없어야합니다. 그러나 나는 카메라에 직면해야한다는 것에 자신을 제한하고 싶지 않습니다. – Helena

+0

성공하고 실패 할 경우 eventData 값은 무엇입니까? – Bijan

+0

레이어 마스크가 필요하지 않습니까? – Maakep

답변

1

일시적으로 IgnoreRaycast 레이어에 떨어 뜨린 개체를 배치하면 내 문제가 해결됩니다. 이것은 또한 광선의 원점을 변환하기 위해 건너 뛸 수 있음을 의미합니다. 위치.

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

Unity의 API로 예외를 포착하지 마십시오. C# IO에서만 그렇게 할 수 있습니다. 코드를 첨부 한 게임 객체 수에 따라 코드를 불필요하게 느리게 만듭니다. 간단히 null 체크를하십시오. – Programmer

+0

마지막으로, 캐치없이, 나쁘지 않은가? 난 그냥 무슨 일이 생기더라도, 내가 게임 객체를 이전에 있던 레이어로 옮겨서 이걸 호출 한 후에 이상한 행동을 피하도록 확실히하고 싶었습니다. – Helena

+0

[JIT는 '보호 된'/ '시도'블록에 대한 최적화를 수행하지 않습니다.] (http://stackoverflow.com/a/1350299/3785314) – Programmer