Search Unity

Getting IPointerEnterHandler to function when dragging with IDragHandler?

Discussion in 'Scripting' started by Harfatum, Sep 5, 2019.

  1. Harfatum

    Harfatum

    Joined:
    May 28, 2018
    Posts:
    9
    I'm making a tile-based matching game, and I would like to be able to drag a tile over other tiles and have the hovered-over tile displace to the empty tile spot without having to let go of the mouse/touch.

    Dragging works fine, but the OnPointerEnter function only gets triggered when I move my mouse so fast that the sprite for the tile I'm dragging lags behind my mouse pointer. I think the event is getting blocked by the sprite. I've tried setting the layer on the dragging tile to 2 or "Ignore Raycast", but this does nothing. Any ideas? (A couple extraneous methods omitted)

    Code (CSharp):
    1. public class Tile : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler
    2. {
    3.     private static Tile currentlyDraggingTile = null;
    4.     private static Vector3 emptyTilePosition;
    5.  
    6.    private SpriteRenderer render;
    7.  
    8.     void Awake() {
    9.        render = GetComponent<SpriteRenderer>();
    10.     }
    11.  
    12.     public void OnBeginDrag(PointerEventData pointerEventData)
    13.     {
    14.         currentlyDraggingTile = this;
    15.         emptyTilePosition = transform.position;
    16.         render.color = new Color(1f, 1f, 1f, 0.7f);
    17.         gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");
    18.     }
    19.  
    20.     public void OnDrag(PointerEventData pointerEventData)
    21.     {
    22.         Vector3 objPosition = Camera.main.ScreenToWorldPoint(pointerEventData.position);
    23.         transform.position = new Vector3(objPosition.x, objPosition.y, transform.position.z);
    24.     }
    25.  
    26.     public void OnEndDrag(PointerEventData pointerEventData)
    27.     {
    28.         currentlyDraggingTile = null;
    29.         render.color = new Color(1f, 1f, 1f, 1f);
    30.         render.sortingOrder = 1;
    31.     }
    32.  
    33.     public void OnPointerEnter(PointerEventData pointerEventData)
    34.     {
    35.         if (!(currentlyDraggingTile is null))
    36.         {
    37.             var currentPosition = transform.position;
    38.             transform.position = emptyTilePosition;
    39.             emptyTilePosition = currentPosition;
    40.         }
    41.     }
    42. }
    43.  
     
    Last edited: Sep 5, 2019
  2. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    You'll probably have more success if you create a visual representation of the tile you're dragging, which doesn't block ray casts, rather than dragging the actual tile.

    So the sequence would go...

    OnBeginDrag: Hide the tile and create/show a drag icon.
    OnDrag: Update the position of the drag icon.
    OnEndDrag: UnHide the tile and destroy/hide the drag icon.

    OnPointerEnter should work as you want then.
     
  3. Harfatum

    Harfatum

    Joined:
    May 28, 2018
    Posts:
    9
    How would I do these? Just setting SpriteRenderer.enabled=false in OnDrag causes the tile to disappear but the OnPointerEnter method still does not trigger except sporadically.
     
  4. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    What are you using as your 'icon' while dragging? Are you sure that it isn't blocking ray casts?
     
  5. Harfatum

    Harfatum

    Joined:
    May 28, 2018
    Posts:
    9
    I set no icon - merely tried disabling the SpriteRenderer in the OnDrag method to see if it would stop blocking the OnPointerEnter from triggering. It did not, at least not reliably. I will worry about the icon when I get the displacement to work. I'm starting to think that I'll just have to convert all my Tiles to UI elements so I can use canvas groups.
     
    Last edited: Sep 6, 2019
  6. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    So you're still dragging the actual tile in the OnDrag method, even though it's hidden?

    The idea is that you leave the dragged tile where it is until EndDrag and only then move it.
     
  7. Harfatum

    Harfatum

    Joined:
    May 28, 2018
    Posts:
    9
    OK, so I disable the SpriteRenderer on the Tile and leave it in the original spot, and then draw a copy of that same image that moves with the mouse cursor. How do I do that? I tried adding an Image to the Tile class, but I'm suspecting that this isn't the right way to go about it (and the list of available images only has "None(Image)" when I try to select one).