UI拖拽 实现接口 1 IBeginDragHandler, IEndDragHandler,IDragHandler
该方法是BeginDrag接口的实现方法,在指定游戏对象被拖拽的时候启用,对于鼠标的位置追踪则可以直接使用 eventData.position 来进行移动,不需要进行一些列转换
一般被拖动的UI会受到自身所在层级影响,因此在一开始就需要重新设置一下被拖动UI的父对象
1 2 3 4 5 6 7 8 public void OnBeginDrag (PointerEventData eventData ) { originParent = transform.parent; this .transform.SetParent(transform.parent.parent.parent); this .transform.position = eventData.position; canvasGroup.blocksRaycasts = false ; }
该方法是EndDrag接口的实现方法,在停止拖拽的时候启用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public void OnEndDrag (PointerEventData eventData ) { if (eventData.pointerCurrentRaycast.gameObject.name.EndsWith("Slot" )) { Debug.Log("----找到合适的位置,准备交换" ); Transform trans = eventData.pointerCurrentRaycast.gameObject.transform; this .transform.SetParent(trans.parent); this .transform.position = trans.position; trans.SetParent(originParent); trans.position = originParent.position; } else if (eventData.pointerCurrentRaycast.gameObject.name.StartsWith("Slot" )) { Transform trans = eventData.pointerCurrentRaycast.gameObject.transform; this .transform.SetParent(trans); this .transform.position = trans.position; } else { Debug.Log("----没有移动到合适的位置,回归原位" ); this .transform.SetParent(originParent); this .transform.position = originParent.position; RectTransform rect = transform as RectTransform; rect.sizeDelta = this .sizeData; } canvasGroup.blocksRaycasts = true ; }
可以使用该方法对射线检测到的物体进行判断
1 eventData.pointerCurrentRaycast.gameObject
拖拽过程中如果不是新生成一个游戏对象作为拖拽副本的话,采用重新设置parent,一来二去会对最后的大小造成影响,因此建议在操作完成后对各自的position进行一设置,position可以是目标地点本来存在的同类游戏对象的position,也可以是目标地的父对象的position
1 2 3 Transform trans = eventData.pointerCurrentRaycast.gameObject.transform; this .transform.SetParent(trans); this .transform.position = trans.position;
配合组件
要注意名字名为 Blocks Raycasts 参数的使用,当为true时,发出的射线不可穿透拖动的物体,fasle反之
射线判断 区域 区域计算 1 2 3 4 5 6 7 8 9 10 11 12 13 RectTransform rectransfrom = itemEquipUI.transform as RectTransform; float w = rectransfrom.rect.width;float h = rectransfrom.rect.height;float x = rectransfrom.position.x;float y = rectransfrom.position.y;float xL = x - w / 2 ;float xR = x + w / 2 ;float yL = y - h / 2 ;float yR = y + h / 2 ; itemEuqipUIArea.Item1 = new Vector2(xL, xR); itemEuqipUIArea.Item2 = new Vector2(yL, yR);
方法调用 1 2 3 4 5 6 if (eventData.position.x.InRange(parentPanel.itemEuqipUIArea.Item1.x, parentPanel.itemEuqipUIArea.Item1.y) && eventData.position.y.InRange(parentPanel.itemEuqipUIArea.Item2.x, parentPanel.itemEuqipUIArea.Item2.y)) { Debug.Log("可以装备Item" ); EquipItem(); }
游戏对象 可以获取拖动UI下方,鼠标正下方的游戏对象
1 eventData.pointerCurrentRaycast.gameObject
注意,该操作的使用前提是
1 canvasGroup.blocksRaycasts = false ;
一般会在拖动开始就将该属性设置为false,但是为了下一次拖拽的稳定可靠,一般会在结束拖动的时候重新设置为true,需要注意要把顺序放置的方法最后,提前设置可能无法获取穿透下方的游戏对象
1 2 3 4 5 public void OnEndDrag (PointerEventData eventData ){ 。。。。。。 canvasGroup.blocksRaycasts = true ; }
相关配置 layout参数配置 使用下图右侧栏目 参数进行配置,可以得到左边的效果。
下图的是在外部大框架没有使用content size filter的情况下使用的,建议使用第一行的第二个参数,会让子元素在空间内均匀排布
示例代码 生成拖动副本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public void OnBeginDrag (PointerEventData eventData ){ itemOnDrag = Instantiate(this .gameObject, this .parentPanel.transform); itemOnDrag.transform.position = eventData.position; } void IDragHandler.OnDrag(PointerEventData eventData){ itemOnDrag.transform.position = eventData.position; Debug.Log(eventData.position); } void IEndDragHandler.OnEndDrag(PointerEventData eventData){ if (eventData.position.x.InRange(parentPanel.itemEuqipUIArea.Item1.x, parentPanel.itemEuqipUIArea.Item1.y) && eventData.position.y.InRange(parentPanel.itemEuqipUIArea.Item2.x, parentPanel.itemEuqipUIArea.Item2.y)) { Debug.Log("可以装备Item" ); EquipItem(); } else if (eventData.position.x.InRange(parentPanel.itemContentUIArea.Item1.x, parentPanel.itemContentUIArea.Item1.y) && eventData.position.y.InRange(parentPanel.itemContentUIArea.Item2.x, parentPanel.itemContentUIArea.Item2.y)) { Debug.Log("可以卸下Item" ); RelieveItem(); } else { Debug.Log("可以丢弃Item" ); DestoryItem(); } Destroy(itemOnDrag); }
本体移动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public void OnBeginDrag (PointerEventData eventData ) { originParent = transform.parent; this .transform.SetParent(transform.parent.parent.parent); this .transform.position = eventData.position; canvasGroup.blocksRaycasts = false ; } public void OnDrag (PointerEventData eventData ) { this .transform.position = eventData.position; Debug.Log("-----射线当前检测到的对象" +eventData.pointerCurrentRaycast.gameObject.name); } public void OnEndDrag (PointerEventData eventData ) { if (eventData.pointerCurrentRaycast.gameObject.name.EndsWith("Slot" )) { Debug.Log("----找到合适的位置,准备交换" ); Transform trans = eventData.pointerCurrentRaycast.gameObject.transform; this .transform.SetParent(trans.parent); this .transform.position = trans.position; trans.SetParent(originParent); trans.position = originParent.position; } else if (eventData.pointerCurrentRaycast.gameObject.name.StartsWith("Slot" )) { Transform trans = eventData.pointerCurrentRaycast.gameObject.transform; this .transform.SetParent(trans); this .transform.position = trans.position; } else { Debug.Log("----没有移动到合适的位置,回归原位" ); this .transform.SetParent(originParent); this .transform.position = originParent.position; RectTransform rect = transform as RectTransform; rect.sizeDelta = this .sizeData; } canvasGroup.blocksRaycasts = true ; }