游戏中有许多单击操作 很多时候要区分普通单击和单击到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;
};
}
}