Unity如何实现反向遮罩并仅让遮罩区域响应点击?
实现不同Canvas下反向遮罩的区域点击限制
核心思路
通过在遮罩Canvas上添加全屏拦截层,仅允许点击圆形遮罩范围内的区域穿透到下方按钮,其余区域直接拦截点击。
具体步骤
1. 调整Canvas层级
确保遮罩Canvas的Sorting Order数值大于按钮所在Canvas,让遮罩显示在按钮上方,优先拦截点击事件。
2. 创建全屏点击拦截层
在遮罩Canvas下新增一个全屏Image(命名为ClickBlocker):
- 设置Image颜色为你需要的遮罩底色(比如半透黑色),拉伸至覆盖整个屏幕。
- 开启
Raycast Target属性,让它拦截所有点击。 - 给这个Image挂载自定义脚本
TutorialClickFilter。
3. 编写点击过滤脚本
using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class TutorialClickFilter : MonoBehaviour, IPointerClickHandler { // 拖拽遮罩里的圆形Image到这里 public Image circleMaskArea; // 可选:直接指定目标按钮,无需射线查找 public Button targetButton; public void OnPointerClick(PointerEventData eventData) { RectTransform maskRect = circleMaskArea.rectTransform; Vector2 localClickPos; // 把屏幕点击坐标转换为遮罩RectTransform的局部坐标 RectTransformUtility.ScreenPointToLocalPointInRectangle( maskRect, eventData.position, eventData.pressEventCamera, out localClickPos); // 判断点击是否在圆形范围内 float clickToCenterDistance = Vector2.Distance(localClickPos, maskRect.rect.center); float circleRadius = maskRect.rect.width / 2f; if (clickToCenterDistance <= circleRadius) { // 点击在允许区域,触发目标按钮或穿透点击 if (targetButton != null) { targetButton.onClick.Invoke(); } else { // 自动查找下方Canvas的可点击元素 foreach (var raycastResult in eventData.raycastResults) { // 跳过遮罩Canvas的元素,只处理目标Canvas的交互物 if (raycastResult.gameObject.GetComponentInParent<Canvas>() != circleMaskArea.GetComponentInParent<Canvas>()) { ExecuteEvents.Execute(raycastResult.gameObject, eventData, ExecuteEvents.pointerClickHandler); break; } } } } // 不在允许区域则直接拦截,不做任何处理 } }
4. 脚本参数配置
- 将遮罩Canvas中的圆形遮罩Image拖到脚本的
circleMaskArea字段。 - 若明确知道目标按钮,直接拖到
targetButton字段;若需要适配动态场景,保留射线查找逻辑即可。
5. 关闭圆形遮罩的射线检测
确保圆形遮罩Image的Raycast Target属性处于关闭状态,避免它本身拦截点击事件。
特殊场景适配
如果圆形遮罩是非标准正圆(比如自定义形状),可以替换距离判断逻辑:
- 使用
RectTransformUtility.RectangleContainsScreenPoint结合形状边界判断; - 读取点击位置的Sprite像素Alpha值,Alpha大于0则视为可点击区域。
内容的提问来源于stack exchange,提问作者Rohit Vishwakarma
相关产品推荐
相关产品推荐

