- [Unity零基础到进阶 | Unity中 屏蔽指定UI点击事件 的多种方法整理](#Unity零基础到进阶 | Unity中 屏蔽指定UI点击事件 的多种方法整理)
-
- [一、Unity中 屏蔽透明区域的点击事件](#一、Unity中 屏蔽透明区域的点击事件)
-
- [1.1 使用Image组件自带的参数检测](#1.1 使用Image组件自带的参数检测)
- [1.2 根据点击的坐标计算该点的像素值是否满足阈值](#1.2 根据点击的坐标计算该点的像素值是否满足阈值)
- [二、Unity中屏蔽 不规则图片按钮点击的事件](#二、Unity中屏蔽 不规则图片按钮点击的事件)
- 总结
🎬 博客主页:https://xiaoy.blog.csdn.net
🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
🎄 学习专栏推荐:Unity系统学习专栏
🌲 游戏制作专栏推荐:游戏制作
🌲Unity实战100例专栏推荐:Unity 实战100例 教程
🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📆 未来很长,值得我们全力奔赴更美好的生活✨
------------------❤️分割线❤️-------------------------
Unity零基础到进阶 | Unity中 屏蔽指定UI点击事件 的多种方法整理
在Unity中 屏蔽UI点击事件的方法有很多种,本文来介绍几种比较实用的方法,一起来看下吧。
一些基础的方法这里简单提一下,例如将Button组件的 Interactable
属性设置为false,可以直接禁用按钮的交互功能。这种方法简单直接,适用于临时禁用或条件性禁用UI元素的情况。
还有通过修改UI元素的isEnabled
属性或监听并处理onClick事件,我们可以在运行时根据游戏逻辑或用户行为来决定是否屏蔽点击事件。这种方法适用于需要复杂逻辑控制或动态响应的场景。
Unity中我们有时候会遇到一些带有透明度或者形状千奇百怪的图片按钮,有些时候可能并不希望点击按钮的透明区域时也触发点击事件,这个时候就要进行额外处理,下面整理了几种方法可以进行参考使用!
一、Unity中 屏蔽透明区域的点击事件
像素检测 过滤透明区域
这种方法是通过读取Sprite在某一点的像素值(RGBA),如果该点的像素值中的Alpha小于一定的阈值(比如0.5)则表示该点是透明的,即用户点击的位置在精灵边界以外,否则用户点击的位置在精灵边界内部。
这种做法就是通过判断点击的某一点是否达到我们期望的像素Alpha阈值,达到阈值就响应事件,未达到阈值就说明点击了透明区域,此时不响应事件。
UGUI在处理控件是否被点击的时候,主要是根据IsRaycastLocationValid这个方法的返回值来进行判断的,而这个方法用到的基本原理则是判断指定点对应像素的RGBA数值中的Alpha是否大于某个指定临界值。
1.1 使用Image组件自带的参数检测
而UGUI中可以通过Image组件拿到一个alphaHitTestMinimumThreshold
,这个值代表的含义就是期望的像素Alpha阈值,通过改变这个值就可以实现过滤透明区域的点击事件。
csharp
this.GetComponent<Image>().alphaHitTestMinimumThreshold = 0.1f;
所以使用方法很简单,拿到指定按钮上的Image组件,改变这个Image的alphaHitTestMinimumThreshold即可实现过滤透明区域的所有点击事件,下面看下实际使用方法及效果。
通过控制alpahThreshold
的值可以实现透明过滤的强度,也就是透明度过滤的阈值。比如alpahThreshold 为0则代表只过滤全透明的区域,alpahThreshold 为0.5则是把半透明一下的过滤掉,alpahThreshold 为1的话那就整张图都被过滤了,都不会响应事件。
准备两个带有透明度的切图,然后放置到场景的Button组件上,测试代码如下:
csharp
using UnityEngine;
using UnityEngine.UI;
public class UnityImageAlphaTest : MonoBehaviour
{
public Button btnImage1;
public Button btnImage2;
[Header("透明度过滤阈值")]
public float alpahThreshold = 0.5f;
void Start()
{
btnImage1.onClick.AddListener(OnClickImage);
btnImage2.onClick.AddListener(OnClickImage);
btnImage2.GetComponent<Image>().alphaHitTestMinimumThreshold = alpahThreshold;
}
private void OnClickImage()
{
Debug.Log("点击图片测试!");
}
}
值得注意的是还需要把过滤透明区域的图片设置为可读写状态(Read/Write Enable 设置为true),如下图所示,否则这种方法不会生效且会报错。
将两个Button挂载到脚本中,第一个Button不参与透明过滤,第二个Button过滤透明区域点击事件。
此时运行Unity就可以看到效果了,效果如下:
1.2 根据点击的坐标计算该点的像素值是否满足阈值
与上述直接使用Image组件的方法有所区别,这种方法是通过计算我们点击的坐标点的像素值是否达到阈值来判断需要过滤。
但原理是相同的,都是通过像素检测去判断是否选择过滤,下面看下实现代码:
csharp
using UnityEngine;
using UnityEngine.UI;
public class Model_ButtonSetting : MonoBehaviour, ICanvasRaycastFilter
{
[Header("透明度过滤阈值")]
public float alpahThreshold = 0.1f;
protected Image _image;
void Start()
{
_image = GetComponent<Image>();
}
public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
//将选中的点转换为Image区域内的本地点
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(_image.rectTransform, sp, eventCamera, out localPoint);
Vector2 pivot = _image.rectTransform.pivot;
Vector2 normalizedLocal = new Vector2(pivot.x + localPoint.x / _image.rectTransform.rect.width, pivot.y + localPoint.y / _image.rectTransform.rect.height);
Vector2 uv = new Vector2(
_image.sprite.rect.x + normalizedLocal.x * _image.sprite.rect.width,
_image.sprite.rect.y + normalizedLocal.y * _image.sprite.rect.height);
uv.x /= _image.sprite.texture.width;
uv.y /= _image.sprite.texture.height;
//获取指定纹理坐标(u, v)处的像素颜色。它返回一个Color结构,其中包含红、绿、蓝和alpha通道的值。
//Color c = _image.sprite.texture.GetPixel((int)uv.x, (int)uv.y);
//用于在纹理上执行双线性插值以获取像素颜色值,这个方法使用双线性插值算法来估算纹理中某个位置的颜色,而不是直接从纹理的像素中读取颜色。
Color c = _image.sprite.texture.GetPixelBilinear(uv.x, uv.y);
return c.a > alpahThreshold;
}
}
这种方法也需要把过滤透明区域的图片设置为可读写状态(Read/Write Enable 设置为true),否则这种方法也不会生效且会报错。
将上述脚本挂载到需要屏蔽透明区域的按钮上即可生效,简单易用。
二、Unity中屏蔽 不规则图片按钮点击的事件
除了上述方法通过检测图片的透明区域来屏蔽点击事件之外,还可以使用 PolygonCollider2D
多边形碰撞组件 来实现不规则图片的事件屏蔽方法,也是简单易用,下面一起看下:
具体事例:
csharp
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(PolygonCollider2D))]
public class PolygonImageClick : MonoBehaviour, ICanvasRaycastFilter
{
/// <summary>
/// 2D多边形碰撞器
/// </summary>
protected PolygonCollider2D m_polygonCollider2D;
protected Image _image;
void Start()
{
_image = GetComponent<Image>();
m_polygonCollider2D = GetComponent<PolygonCollider2D>();
}
public bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
Vector3 worldPos;
//将屏幕上的点转换为世界坐标中的点,考虑到了矩形(RectTransform)的本地坐标系
RectTransformUtility.ScreenPointToWorldPointInRectangle(_image.rectTransform, screenPoint, eventCamera, out worldPos);
return m_polygonCollider2D.OverlapPoint(worldPos);
}
}
通过继承一个ICanvasRaycastFilter 接口,实现 IsRaycastLocationValid() 方法,在方法中判断某点是否在多边形碰撞器区域内即可实现不规则区域的点击。
将上述代码挂载到有Image的组件上,然后调整多边形不规则形状用来适配我们的不规则图片。
调整好多边形后运行游戏,即可实现只在多边形区域内可以实现点击事件,其他区域就被过滤掉了。
效果如下:
这种方法不止可以过滤掉透明区域,还可以让我们随意指定范围,并且不需要将图片设置为可读写状态(Read/Write Enable 开启后加载时会多一份内存消耗),内存也不会白白多浪费,比起前面几种方法有更高的扩展性。
总结
-
在Unity游戏开发过程中,UI(用户界面)的设计和管理是至关重要的一环。有时,开发者可能希望屏蔽或禁用某些UI元素的点击事件,以避免不必要的交互或错误操作。
-
Unity中屏蔽指定UI点击事件的方法多种多样,从简单的属性设置到复杂的脚本编程和高级技术应用,每种方法都有其适用的场景和优缺点。开发者可以根据具体需求选择合适的方法来实现UI点击事件的屏蔽,从而提升游戏的用户体验和稳定性。