2017-01-19 7 views
0

Я реализовал компонент Unity, который реализует IDragHandler, а другой, который реализует IDropHandler. Компонент IDragHandler помещается в объект, который я хочу перетащить, но компонент IDropHandler привязан к объектам, которые я могу удалить объекты на, а не объекты, которые I может упасть.Unity IDropHandler с 2D объектами в 3D-пространстве

Я работаю в 3D с перспективной камерой.

Мой код ниже отлично подходит для удаления 3D-объектов на 3D-объектах и ​​трехмерных объектов на объектах 2D-интерфейса, но не для удаления объектов 2D-интерфейса на трехмерных объектах или объектах двумерного UI на объектах 2D-интерфейса.

Проблема, с которой я столкнулся, заключается в том, что объект, который я перетаскиваю, блокирует OnDrop и берет его для себя из-за Raycasting EventSystem (даже если я не реализую IDropHandler на этом объекте).

Для 3D-объектов временно отключите коллайдер, перетаскивая компонент IDragHandler, чтобы убедиться, что Raycast, который решает, какой объект дает OnDrop, проходит по перетаскиваемому объекту и к объекту позади него. Однако объекты 2D UI не работают с коллайдерами для перетаскивания, поэтому коллайдер не доступен для отключения. Я не знаю, как убедиться, что EventSystem Raycast обходит перетаскиваемый объект, чтобы передать OnDrop объекту позади него.

public void OnBeginDrag(PointerEventData eventData) 
    { 
     ... 

     if (UIObject) 
     { 
      // What to do here? 
     } 
     else 
     { 
      var collider = gameObject.GetComponent<Collider>(); 
      collider.enabled = false; 
     } 

    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     // Move object and stuff 
     ... 
    } 

    public void OnEndDrag(PointerEventData eventData) 
    { 
     if (UIObject) 
     { 
      // What to do here? 
     } 
     else 
     { 
      var collider = gameObject.GetComponent<Collider>(); 
      collider.enabled = true; 
     } 
    } 

Вещи я пытался до сих пор является:

1) Временно установите геймобжекты в слое IgnoreRaycast

2) Добавить холст группы к объекту и временно отключить «Block Raycast ".

Ничего из того, что я делаю в OnBeginDrag, по-видимому, имеет эффект до тех пор, пока я действительно не уронил объект по какой-либо причине. Попытка № 2, упомянутая выше, привела к тому, что она не отключила «Block Raycast» до тех пор, пока объект не был удален, что заставило объект даже не перетащить.

ответ

0

Я сделал обходной путь, где перетащил объект в raycasts OnEndDrag и обнаружил, что он был сброшен на что-то, и если это так, вызывает OnDrop на этом объекте. Теперь отключение и включение коллайдеров на 3D-объекте устарело, поэтому оно было удалено.

public void OnBeginDrag(PointerEventData eventData) 
    { 
     ... 
    } 

    public void OnDrag(PointerEventData eventData) 
    { 
     // Move object and stuff 
     ... 
    } 

    public void OnEndDrag(PointerEventData eventData) 
    { 
     // Currently using transform.position as raycast origin, could easily be something else if desired. 
     var rayCastOrigin = transform.position; 

     // 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 raycastOriginInScreenSpace = Camera.main.WorldToScreenPoint(rayCastOrigin); 
     var screenRay = Camera.main.ScreenPointToRay(new Vector3(raycastOriginInScreenSpace.x, raycastOriginInScreenSpace.y, 0.0f)); 

     // Perform Physics.Raycast from transform and see if any 3D object was under transform.position on drop. 
     RaycastHit hit3D; 
     if (Physics.Raycast(screenRay, out hit3D)) 
     { 
      var dropComponent = hit3D.transform.gameObject.GetComponent<IDropHandler>(); 
      if (dropComponent != null) 
       dropComponent.OnDrop(eventData); 
     } 

     // Perform Physics2D.GetRayIntersection from transform and see if any 2D object was under transform.position on drop. 
     RaycastHit2D hit2D = Physics2D.GetRayIntersection(screenRay); 
     if (hit2D) 
     { 
      var dropComponent = hit2D.transform.gameObject.GetComponent<IDropHandler>(); 
      if (dropComponent != null) 
       dropComponent.OnDrop(eventData); 
     } 

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

поведение я хотел, что, когда transform.position объекта падает на что-то, то это считается как упал. Поведение по умолчанию, что, когда указатель мыши находится внутри объекта упала она вызывает OnDrop, легко может быть достигнуто путем обмена

var raycastOriginInScreenSpace = Camera.main.WorldToScreenPoint(rayCastOrigin); 
var screenRay = Camera.main.ScreenPointToRay(new Vector3(raycastOriginInScreenSpace.x, raycastOriginInScreenSpace.y, 0.0f)); 

с

var screenRay = Camera.main.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, 0.0f));