判断是否单击到UI及拖动UI控件的两种方法

1 篇文章 0 订阅

游戏中有许多单击操作 很多时候要区分普通单击和单击到UI的操作

private void Update()
    {
        if (Input.GetMouseButton(0)) 
        {
            if (EventSystem.current.IsPointerOverGameObject() || GUIUtility.hotControl != 0) 
            {
                Debug.Log("单击到UI");
            }
            else
            {
                Debug.Log("没有单击到UI");
            }
        }
    }

在窗口端进行判断时使用: 

EventSystem.current.IsPointerOverGameObject()方法,作用:判断鼠标是否点击在UI

GUIUtility.hotControl = id;

为每个GUI分配一个ControlID,此ID使每个GUI独立,如果没有正确分配这个ID,你最终会遇到多个GUI操作的冲突.在用OnGUI函数绘制窗体时,鼠标在窗体或控件上面操作时,场景则不应该响应鼠标事件。网上一般用 GUIUtility.hotcontrol!=0来屏蔽,当hotControl不为0时说明有控件处于激活状态。查官方文档,当鼠标在GUI控件上面按下时,hotcontrol被设置为该控件的ID,当鼠标按键被弹起时,hotcontrol为设置为0,因为在场景里面只能配合鼠标按下事件,不能配合鼠标弹起,因为此时hotcontrol已经被引擎置为0了。 但是目前开发的界面上发现,偶尔在窗体上点击时,hotcontrol仍然为0,因此不能完全屏蔽掉GUI的操作。不知道有人知道什么原因么?现在只好做一个全局标记变量,每个界面负责管理这个变量,当鼠标在某个界面内,则把标记置为true。离开或界面被关闭,则置为false。

新建一个背景图,以其为父物体,再建两个都是Image的子物体.我们将拖动左边的物体和右边的物体重合.两种方法,一个是用触发系统,繁琐,一个用Unity封装好的接口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragTest1 : MonoBehaviour
{
    private RectTransform dragArea;//拖动区域
    private Image imageDrag;//拖动图像
    private Image imageTarget;//目标区域

    private void Awake()
    {
        dragArea = GameObject.Find("RawImage").GetComponent<RectTransform>();
        imageDrag = transform.Find("Image Target").GetComponent<Image>();
        imageTarget = transform.Find("Image Drag").GetComponent<Image>();
    }
    void Start()
    {
        EventTrigger trigger = imageDrag.gameObject.AddComponent<EventTrigger>();
        EventTrigger.Entry dragentry = new EventTrigger.Entry();
        dragentry.eventID = EventTriggerType.Drag;//创建一个拖动事件
        dragentry.callback = new EventTrigger.TriggerEvent();
        dragentry.callback.AddListener(delegate (BaseEventData eventData)
        {
            Vector2 touchpos = ((PointerEventData)eventData).position;//获得当前拖动的屏幕坐标
            Vector2 uguiPos;
            //将屏幕坐标转换为UGUI的本地坐标
            bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(dragArea, touchpos, ((PointerEventData)eventData).enterEventCamera, out uguiPos);
            //如果拖动位置在区域内
            if (isRect && RectTransformUtility.RectangleContainsScreenPoint(dragArea,touchpos,((PointerEventData)eventData).enterEventCamera))
            {
                //更新被拖动图象的位置
                imageDrag.rectTransform.localPosition = uguiPos;
            }
            //拖动的时候防止阻挡射线检测
            imageDrag.raycastTarget = false;
        });

        EventTrigger.Entry enddragentry = new EventTrigger.Entry();
        enddragentry.eventID = EventTriggerType.EndDrag;//结束拖动事件
        enddragentry.callback = new EventTrigger.TriggerEvent();
        enddragentry.callback.AddListener(delegate (BaseEventData eventData)
        {
            var go = ((PointerEventData)eventData).pointerEnter;
            //如果拖动到目标位置
            if (go != null && go.name.CompareTo("image Target") == 0) 
            {
                imageDrag.rectTransform.position = imageTarget.rectTransform.position;
            }
            imageDrag.raycastTarget = true;
        });
        trigger.triggers.Add(dragentry);
        trigger.triggers.Add(enddragentry);
    }
    //private void Update()
    //{
    //    if (Input.GetMouseButton(0)) 
    //    {
    //        if (EventSystem.current.IsPointerOverGameObject() || GUIUtility.hotControl != 0) 
    //        {
    //            Debug.Log("单击到UI");
    //        }
    //        else
    //        {
    //            Debug.Log("没有单击到UI");
    //        }
    //    }
    //}
}

这里的代码主要是触发了两个事件 一个是拖动事件:dragentry.eventID = EventTriggerType.Drag;

一个是结束拖动的事件:enddragentry.eventID = EventTriggerType.EndDrag;

在拖动事件中 获取到屏幕坐标位置 并将屏幕坐标转换为UGUi的本地坐标 实现拖动效果;在拖动结束后 判断是否拖动到目标位置并更新位置

首先 创建一个类 继承接口IDragHandler IEndDragHandler接口 实现他们的接口方法

即可获得拖动后的位置 这个类要被挂到被拖动的UI控件上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;//事件系统

public class DragImage : MonoBehaviour, IDragHandler, IEndDragHandler
{
    public System.Action<PointerEventData> onDragEvent;//委托拖拽事件回调
    public System.Action<PointerEventData> onDragEndEvent;//委托拖曳结束事件回调
    public void OnDrag(PointerEventData eventData)
    {
        if (onDragEvent != null)
        {
            onDragEvent(eventData);//响应开始拖曳
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (onDragEndEvent != null)
        {
            onDragEndEvent(eventData);//响应结束拖曳
        }
    }
}

创建脚本 大致和上一种拖曳方法一样

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragTest2 : MonoBehaviour
{
    private RectTransform dragArea;
    public DragImage imageDrag;//继承拖曳接口
    private Image imageTarget;
    private void Awake()
    {
        dragArea = GameObject.Find("RawImage").GetComponent<RectTransform>();
        imageTarget = dragArea.Find("Image Target").GetComponent<Image>();
    }
    private void Start()
    {
        imageDrag.onDragEvent += (PointerEventData eventData) =>
        {
            Vector2 touchPos = eventData.position;//获得当前拖动的屏幕坐标位置
            Vector2 uguiPos;
            bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(dragArea, touchPos, eventData.enterEventCamera, out uguiPos);
            if (isRect && RectTransformUtility.RectangleContainsScreenPoint(dragArea, touchPos, eventData.enterEventCamera)) 
            {
                imageDrag.GetComponent<RectTransform>().localPosition = uguiPos;
                imageDrag.GetComponent<Image>().raycastTarget = false;
            }
        };
        imageDrag.onDragEndEvent+=(PointerEventData eventData)=>{
            var go = ((PointerEventData)eventData).pointerEnter;
            if (go != null && go.name.CompareTo("image Target") == 0) 
            {
                imageDrag.GetComponent<RectTransform>().position = imageTarget.rectTransform.position;
            }
            imageDrag.GetComponent<Image>().raycastTarget = true;
        };
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值