参考:https://ask.csdn.net/questions/7971448
根据自己的需求修改为如下代码
使用过程中,出现拖动ui位置错误的情况,修改为使用 localPosition
但是吸附到指定位置却需要用的position
public class DragAndDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{private RectTransform dragTransform;private Vector2 initPosition;private Vector2 startPosition;[Header("正确区域")]public RectTransform targetArea;[Header("初始区域")]public RectTransform originalArea;[Header("错误区域")]public RectTransform[] targetOtherArea;private bool result; //拖动结果private bool valid; //拖动有效public bool Result { get => result; private set => result = value; }public bool Valid { get => valid; private set => valid = value; }public void Awake(){dragTransform = GetComponent<RectTransform>();//初始位置initPosition = dragTransform.localPosition;}/// <summary>/// 重置位置/// </summary>public void ResetPos(){dragTransform.localPosition = initPosition;result = false;valid = false;}public void OnBeginDrag(PointerEventData eventData){//开始拖动的位置startPosition = dragTransform.localPosition;//设置UI最后渲染dragTransform.SetAsLastSibling();}public void OnDrag(PointerEventData eventData){dragTransform.localPosition = GetLocalPosition(eventData.position);}public void OnEndDrag(PointerEventData eventData){result = RectTransformUtility.RectangleContainsScreenPoint(targetArea, eventData.position);
#if UNITY_EDITORDebug.Log($"拖动结果: {result}");
#endifif (result){//吸附到目标位置dragTransform.position = targetArea.position;valid = true;return;}else{foreach (var item in targetOtherArea){if (RectTransformUtility.RectangleContainsScreenPoint(item, eventData.position)){//吸附到目标位置dragTransform.position = item.position;valid = true;return;}}//原始位置,拖动无效if (RectTransformUtility.RectangleContainsScreenPoint(originalArea, eventData.position)){//吸附到目标位置dragTransform.position = originalArea.position;valid = false;return;}}//其它情况还原为开始拖动的位置valid = false;dragTransform.localPosition = startPosition;}private Vector2 GetLocalPosition(Vector2 screenPosition){Vector2 localPosition = Vector2.zero;RectTransformUtility.ScreenPointToLocalPointInRectangle(dragTransform.parent as RectTransform, screenPosition, null, out localPosition);return localPosition;}}
Demo
using MyTool.Tools;
using UnityEngine;
using UnityEngine.UI;public class Demo : MonoBehaviour
{public DragAndDrop dragAndDrop;public Button okBtn;// Start is called before the first frame updatevoid Start(){okBtn.onClick.AddListener(OnClickOkBtn);}private void Update(){okBtn.interactable = dragAndDrop.Valid;}void OnClickOkBtn(){if (dragAndDrop.Result){Debug.Log("恭喜你答对了!");}else{Debug.Log("很遗憾,没有答对!");}}
}
ui搭建
效果