2017-01-19 8 views
0

IDragHandlerを実装するUnityコンポーネントと、IDropHandlerを実装するUnityコンポーネントを実装しました。 IDragHandlerコンポーネントはドラッグするオブジェクトに配置されますが、IDropHandlerコンポーネントはオブジェクトをにドロップでき、はドロップできないオブジェクトはにドロップできます。3D空間内の2Dオブジェクトを持つUnity IDropHandler

私は遠近法カメラで3Dで作業しています。

以下のコードは、3Dオブジェクト上の3Dオブジェクト、2D UIオブジェクト上の3Dオブジェクトをドロップするのには問題ありませんが、3Dオブジェクト上の2D UIオブジェクトまたは2D UIオブジェクト上の2D UIオブジェクトをドロップすることはできません。

私が持っていた問題は、ドラッグしているオブジェクトがOnDropをブロックし、EventSystemのレイキャスティング(そのオブジェクトにIDropHandlerを実装していなくても)のためにそれを取ることです。

3Dオブジェクトの場合、IDragHandlerコンポーネントでドラッグしながらColliderを一時的に無効にして、OnDropを与えるオブジェクトを決定するRaycastがドラッグされたオブジェクトとその背後のオブジェクトを通過することを確認します。 しかし、2DのUIオブジェクトは、ドラッグアンドドロップのためにコライダーでは機能しないため、無効にできるコライダーはありません。 EventSystemレイキャストがドラッグされたオブジェクトをバイパスして、その背後のオブジェクトに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でゲームオブジェクトを配置)オブジェクトにキャンバスグループを追加し、一時的にオフにする「ブロックレイキャスト "と言いました。

私は実際に何らかの理由でオブジェクトを削除するまで、OnBeginDragで何もしないようです。上記の#2を試してみると、オブジェクトがドロップされるまで「ブロックレイキャスト」がオフにならず、オブジェクトがもはやドラッグできなくなってしまいました。

答えて

0

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)); 
関連する問題