- Home /
drag/drop ui. but not onto other elements?
Hi so im trying to create a nice drag and drop function for my inventory. i have it mostly complete but what id like to do is have it so i cant drop the item onto another item. you can see what im trying to avoid in the gif below
https://gyazo.com/b761633bd857bfd53ce911ef25488e2c
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ItemSlot : MonoBehaviour, IPointerDownHandler,IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, IDragHandler
{
public GameObject toolTip;
public Text ItemName;
public Text ItemDesc;
public Text ItemAmount;
public Text ItemWeight;
public Transform player;
Vector3 startPos;
public bool draging;
public Item item;
private GameObject InvUi;
void Update()
{
if (transform.name == "")
{
gameObject.SetActive(false);
}
GetComponent<Image>().sprite = Resources.Load<Sprite>("Sprites/" + item.ItemName);
ItemName.text = item.ItemName;
ItemDesc.text = item.ItemDescription;
ItemAmount.text = item.ItemAmount.ToString();
float weight = item.ItemAmount * item.ItemWeight;
ItemWeight.text = weight.ToString();
InvUi = GameObject.Find("HUDCanvas/InventoryUI");
if (draging)
{
transform.position = Input.mousePosition;
}
}
public void OnPointerDown(PointerEventData data)
{
draging = true;
startPos = transform.position;
}
public void OnPointerUp(PointerEventData data)
{
if (RectTransformUtility.RectangleContainsScreenPoint(InvUi.transform.GetComponent<RectTransform>(), transform.position, null))
{
draging = false;
}
else
{
player.GetComponent<Inventory>().dropItem(item);
draging = false;
transform.position = startPos;
toolTip.SetActive(false);
}
}
public void OnDrag(PointerEventData data)
{
}
public void OnEndDrag(PointerEventData eventData)
{
}
public void OnPointerEnter(PointerEventData data)
{
toolTip.SetActive(true);
}
public void OnPointerExit(PointerEventData data)
{
toolTip.SetActive(false);
}
}
Answer by SohailBukhari · Jun 05, 2017 at 06:33 AM
UI elements under Canvas objects are rendered according to their hierarchy. Objects at the bottom will be rendered on top.
transform.SetAsLastSibling(); //move to the front (on parent)
transform.SetAsFirstSibling(); //move to the back (on parent)
transform.SetSiblingIndex( 2 ); //move to position, whereas 0 is the backmost,
transform.parent.childCount -1 is the frontmost position
transform.GetSiblingIndex(); //get the position in the hierarchy (on parent)
Detailed:
UGUI renders all the UI objects based on their hierarchy in the project. The more superior an object is in the hierarchy, the earlier it is rendered, and thus it is displayed "deeper" on the screen. So the problem is how to change the hierarchy of the objects, both during the editing and running. In editing mode you may just change the priority of the siblings in the hierarchy -- drag and drop, that is easy. If you want to change the relationship during running time, you definitely need to script and you may take this official document for reference: Official Scripting API So now lets make some examples. How to make a text rendered in front of all the siblings, its parent and all the other objects placed above the parent in the hierarchy:
text.transform.SetAsLastSibling (); //Since it is rendered the latest, it is displayed on the top.
How to make a sprite rendered behind any other UI objects of its siblings:
sprite.transform.SetAsFirstSibling ();
Suppose that you have 8 siblings under a parent, and you know that a text is the last sibling, a sprite is the 6th sibling. How to make a sprite rendered between the text and the sprite:
anotherSprite.transform.SetSiblingIndex (7);
the sprite's sibling order, how to get it:
int spriteOrder = sprite.transform.GetSiblingIndex ();
For Draging stuff I just do this :
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Draggable : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
public void OnBeginDrag(PointerEventData eventData) {
}
public void OnDrag(PointerEventData eventData) {
//Debug.Log ("OnDrag");
this.transform.position = eventData.position;
}
public void OnEndDrag(PointerEventData eventData) {
Debug.Log ("OnEndDrag");
}
}
ahh ok so i believe my question wasn't clear enough what im trying to do is if my item is over another item it wil stop the dragging from beco$$anonymous$$g false so that i can only actually stop dragging if its not over another item
you can modify the PointerEventData info that is passed into the OnBeginDrag function - specifically, set pointerDrag to null. This will cancel the drag:
eventData.pointerDrag = null;
how do i check if its over another item tho. thats what im asking. i cant use ray casts as i have an item over the mouse pos