欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

unity如何获得响应鼠标点击的ui gameObject

程序员文章站 2022-07-12 23:31:40
...

转自Unity获取鼠标点击ui GameObject

最近拼ui烦躁得很,经常button被各种遮挡=。=

unity没有提供获取鼠标点中哪个ui GameObject的接口,网上也只有一堆简单的判断是不是点在ui上的判断,还以为要像以前那样,要去看源码,各种反射拿出数据。

结果源码的确看了,但是并不需要各种反射,只需要简单的几句话就能实现了。

话不多说,直接上代码。

 

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

public class ClickListener : MonoBehaviour
{
	List<RaycastResult> list = new List<RaycastResult>();

	// Update is called once per frame
	    void Update()
	    {
		/// 鼠标左键没有点击,就不执行判断逻辑
		if(!Input.GetMouseButtonDown(0))
		{
			return;
		}

		///相应的GameObject对象
		GameObject go = null;

		///判断是否点再ui上
		if (EventSystem.current.IsPointerOverGameObject())
		{
			go = ClickUI();
		}
		else
		{
			go = ClickScene();
		}

		if (go == null)
		{
			Debug.Log("Click Nothing");
		}
		else
		{
			// 高亮点中GameObject
			EditorGUIUtility.PingObject(go);
			Selection.activeObject = go;
			Debug.Log(go, go);
		}

	}

	/// <summary>
	/// 点中ui
	/// </summary>
	private GameObject ClickUI()
	{
		//场景中的EventSystem

		PointerEventData eventData = new PointerEventData(EventSystem.current);

		//鼠标位置
		eventData.position = Input.mousePosition;

		//调用所有GraphicsRacaster里面的Raycast,然后内部会进行排序,
		//直接拿出来,取第一个就可以用了
		EventSystem.current.RaycastAll(eventData, list);

		//这个函数抄的unity源码的,就是取第一个值
		var raycast = FindFirstRaycast(list);

		//获取父类中事件注册接口
		//如Button,Toggle之类的,毕竟我们想知道哪个Button被点击了,而不是哪张Image被点击了
		//当然可以细分为IPointerClickHandler, IBeginDragHandler之类细节一点的,各位可以自己取尝试
		var go = ExecuteEvents.GetEventHandler<IEventSystemHandler>(raycast.gameObject);
		
		//既然没拿到button之类的,说明只有Image挡住了,取点中结果即可
		if (go == null)
		{
			go = raycast.gameObject;
		}
		return go;

		
	}

	/// <summary>
	/// Return the first valid RaycastResult.
	/// </summary>
	private RaycastResult FindFirstRaycast(List<RaycastResult> candidates)
	{
		for (var i = 0; i < candidates.Count; ++i)
		{
			if (candidates[i].gameObject == null)
				continue;

			return candidates[i];
		}
		return new RaycastResult();
	}

	/// <summary>
	/// 点中场景中对象
	/// 然后无聊嘛,顺便把点场景的也顺手做了,不过这部分网上介绍挺多的,就不展开说了。
	/// </summary>
	private GameObject ClickScene()
	{
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit hit;
		if (Physics.Raycast(ray, out hit))
		{
			GameObject go = hit.collider.gameObject;
			return go;
		}

		return null;
	}
}

效果预览

unity如何获得响应鼠标点击的ui gameObject