{"id":451,"date":"2017-05-27T08:00:00","date_gmt":"2017-05-27T07:00:00","guid":{"rendered":"https:\/\/pagan-gerbil.net\/?p=451"},"modified":"2017-05-27T08:00:00","modified_gmt":"2017-05-27T07:00:00","slug":"drag-and-drop-in-unity-part-one","status":"publish","type":"post","link":"https:\/\/www.pagan-gerbil.net\/?p=451","title":{"rendered":"Drag and Drop in Unity Part One"},"content":{"rendered":"<p>I\u2019m starting to experiment with <a href=\"http:\/\/www.unity3d.com\">Unity<\/a> for a hobby project involving a card game.<\/p>\n<p>In almost any card game, there are certain areas of the table for a collection of cards. Whether this is the vertical stack in Solitaire, the lands in Magic: The Gathering or a hidden hand of cards that aren\u2019t \u2018on\u2019 the table, there are different areas that contain groups of cards. These cards will usually need to move between the card containers, so I figured the first thing to do would be to implement dragging and dropping. After watching a few video tutorials (the most useful was <a href=\"https:\/\/www.youtube.com\/watch?v=c47QYgsJrWc\">this one<\/a>), I was ready to try some things out.<\/p>\n<p>I started with a 2D game in Unity \u2013 card games are famously 2-dimensional. To this, I added a Panel and named it \u201cContainer\u201d. Then I added a Panel inside the Container and named it \u201cItem\u201d. I made the Containers a little bigger than the Items so it was easier to see them, and duplicated this until there were 4.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" title=\"\" style=\"border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; float: none; padding-top: 0px; padding-left: 0px; margin-left: auto; border-left: 0px; display: block; padding-right: 0px; margin-right: auto\" border=\"0\" alt=\"\" src=\"https:\/\/pagan-gerbil.net\/wp-content\/uploads\/2017\/05\/image-1.png\" width=\"600\" height=\"327\"><\/p>\n<p>I added a Grid Layout component to all of the \u201cContainer\u201d objects and set the Child Alignment to \u2018Middle Center\u2019, then added a Constraint of \u2018Fixed Row Count\u2019 and the Constraint Count to 1 so that each container would only ever have one row of items.<\/p>\n<p>Each \u201cItem\u201d needed a script \u2013 named DragHandler \u2013 to handle the dragging behaviour. The script describes how the object should behave when being dragged around, including how to begin dragging it in the first place. To do this it needs to reference the UnityEngine.EventSystems namespace, and implement the three interfaces IBeginDragHandler, IDragHandler and IEndDragHandler.<\/p>\n<p>First of all, it needs some properties and fields set up.<\/p>\n<pre>public static GameObject ItemBeingDragged;\nprivate Vector2 _startPosition;\nprivate Transform _startParent;<\/pre>\n<p>This is almost verbatim from the tutorial video, and I will probably be refactoring that static GameObject field at some point in the future (it ought to be a property if it\u2019s public).<\/p>\n<pre>public void OnBeginDrag(PointerEventData eventData)\n{&nbsp;&nbsp;&nbsp;&nbsp; ItemBeingDragged = gameObject;&nbsp;&nbsp;&nbsp;&nbsp; _startPosition = transform.position;&nbsp;&nbsp;&nbsp;&nbsp; _startParent = transform.parent;&nbsp;&nbsp;&nbsp;&nbsp; GetComponent&lt;CanvasGroup&gt;().blocksRaycasts = false;\n}<\/pre>\n<p>OnBeginDrag starts the process off by setting the ItemBeingDragged to the current GameObject, saving the start position (so it can be returned later if the drop is unsuccessful) and saving the original parent (same reason). Finally it finds the CanvasGroup component and stops blocking raycasts so that events can be fired through the item being dragged (this will be needed to drop it).<\/p>\n<pre>public void OnDrag(PointerEventData eventData)\n{&nbsp;&nbsp;&nbsp;&nbsp; transform.position = Input.mousePosition;\n}<\/pre>\n<p>OnDrag just makes the dragged item follow the mouse cursor until it is dropped.<\/p>\n<pre>public void OnEndDrag(PointerEventData eventData)\n{&nbsp;&nbsp;&nbsp;&nbsp; ItemBeingDragged = null;&nbsp;&nbsp;&nbsp;&nbsp; if (_startParent == transform.parent)&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transform.position = _startPosition;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp; GetComponent&lt;CanvasGroup&gt;().blocksRaycasts = true; \n}<\/pre>\n<p>Finally, when the drag is over, the ItemBeingDragged is forgotten (set to null), and if the parent item at the end is the same as the beginning it is returned to it\u2019s starting position. Finally, raycast blocking is restored so it can pick up further events.<\/p>\n<p>The Container objects need a script too, which will also need to reference UnityEngine.EventSystems and implement an interface. This time, IDropHandler so we can drop items there.<\/p>\n<pre>public void OnDrop(PointerEventData eventData)\n{&nbsp;&nbsp;&nbsp;&nbsp; DragHandler.ItemBeingDragged.transform.SetParent(transform);\n}<\/pre>\n<p>This is a simple script. It references the static ItemBeingDragged property from the DragHandler script, and sets its parent to whatever the drop target is.<\/p>\n<p>With all this set up, I can drag Item panels from one Container to another. Or move a card from one location to another, eventually.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019m starting to experiment with Unity for a hobby project involving a card game. In almost any card game, there are certain areas of the table for a collection of cards. Whether this is the vertical stack in Solitaire, the lands in Magic: The Gathering or a hidden hand of cards that aren\u2019t \u2018on\u2019 the &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.pagan-gerbil.net\/?p=451\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Drag and Drop in Unity Part One&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14],"tags":[194,195,62,196],"series":[],"_links":{"self":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts\/451"}],"collection":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=451"}],"version-history":[{"count":0,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=\/wp\/v2\/posts\/451\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=451"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=451"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=451"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.pagan-gerbil.net\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=451"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}