Unity基于NGUI点击事件向下传递的解决方法

2023-11-01

Unity开发中经常有点击Button,弹窗提示界面,然后点击任意区域关闭提示界面并且提示界面下一层的事件依然可以触发;需要点击事件向下传递;UGUI对此支持相对好处理,NGUI本身对此支持不好;这里提供一个方法:

public class UIClickOutWidget : MonoBehaviour
{
    public UIWidget BGWidget;//界面widget
    public UIWidget TargetWidget;//触发按钮widget
    public float ClickDistance = 10f; //判断点击的范围
    bool beganInWidget = false; //记录触屏开始是否在BGWidget内(当在BGWidget内,需要点击才关闭,滑动则不关闭)
    Vector3 beganPos = Vector3.zero;//记录触屏开始的坐标
	// Update is called once per frame
	void Update ()
    {
        if (!gameObject.activeSelf)
            return;
        if(Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
        {
            if (Input.touchCount > 0)
            {
                Touch touch = Input.GetTouch(0);
                if (touch.phase == TouchPhase.Began || touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
                {
                    if(touch.phase == TouchPhase.Began)
                    {
                        beganPos = touch.position;
                        beganInWidget = IsClickInWidget(touch.position, BGWidget);
                        //触屏开始,如果不在界面BGWidget内,则直接关闭
                        if(!beganInWidget)
                        {
                            //如果点击在触发按钮上,则不关闭;需要通过触发按钮关闭
                            bool isInTarWidget = IsClickInWidget(touch.position, TargetWidget);
                            if (!isInTarWidget)
                                DeactiveUI();
                        }
                    }
                    else
                    {
                        //触屏结束,是点击则关闭界面
                        if(IsClick(beganPos, touch.position))
                        {
                            //如果点击在触发按钮上,则有触发按钮关闭;此处不关闭
                            bool isInTarWidget = IsClickInWidget(touch.position, TargetWidget);
                            if (!isInTarWidget)
                                DeactiveUI();
                        }
                        else if(!beganInWidget)//触屏结束,不是点击并且起始点不在BGWidget内,则关闭
                        {
                            //如果点击在触发按钮上,则有触发按钮关闭;此处不关闭
                            bool isInTarWidget = IsClickInWidget(touch.position, TargetWidget);
                            if (!isInTarWidget)
                                DeactiveUI();
                        }
                    }
                }
            }
        }
        else
        {
            if (Input.GetMouseButtonUp(0) || Input.GetMouseButtonDown(0))
            {
                if (Input.GetMouseButtonDown(0))
                {
                    beganPos = Input.mousePosition;
                    beganInWidget = IsClickInWidget(Input.mousePosition, BGWidget);
                    //触屏开始,如果不在界面BGWidget内,则直接关闭
                    if (!beganInWidget)
                    {
                        //如果点击在触发按钮上,则不关闭;需要通过触发按钮关闭
                        bool isInTarWidget = IsClickInWidget(Input.mousePosition, TargetWidget);
                        if(!isInTarWidget)
                            DeactiveUI();
                    }
                }
                else
                {
                    //触屏结束,是点击则关闭界面
                    if (IsClick(beganPos, Input.mousePosition))
                    {
                        //如果点击在触发按钮上,则有触发按钮关闭;此处不关闭
                        bool isInTarWidget = IsClickInWidget(Input.mousePosition, TargetWidget);
                        if (!isInTarWidget)
                            DeactiveUI();
                    }
                    else if (!beganInWidget)//触屏结束,不是点击并且起始点不在BGWidget内,则关闭
                    {
                        //如果点击在触发按钮上,则有触发按钮关闭;此处不关闭
                        bool isInTarWidget = IsClickInWidget(Input.mousePosition, TargetWidget);
                        if (!isInTarWidget)
                            DeactiveUI();
                    }
                }
            }
        }
    }

    void DeactiveUI()
    {
        gameObject.SetActive(false);
        --添加需要关闭的UI界面
        beganPos = Vector3.zero;
        beganInWidget = false;
    }

    bool IsClick(Vector3 beganPos, Vector3 endPos)
    {
        if (beganPos == Vector3.zero)
            return true;
        Vector3 temp = endPos - beganPos;
        return Mathf.Abs(temp.x) < ClickDistance && Mathf.Abs(temp.y) < ClickDistance;
    }

    //判断点击坐标是否在wdiget范围内
    bool IsClickInWidget(Vector3 pos, UIWidget widget)
    {
        if (widget == null)
            return false;
        Vector3 localPos = widget.transform.localPosition;
        Vector3 screenPos = UICamera.currentCamera.ScreenToWorldPoint(pos);
        Vector3 mousePos = widget.transform.parent.InverseTransformPoint(screenPos);
        float minX = localPos.x - widget.width / 2;
        float maxX = localPos.x + widget.width / 2;
        float minY = localPos.y - widget.height / 2;
        float maxY = localPos.y + widget.height / 2;
        if (widget.pivot == UIWidget.Pivot.Left || widget.pivot == UIWidget.Pivot.BottomLeft || widget.pivot == UIWidget.Pivot.TopLeft)
        {
            minX = localPos.x;
            maxX = localPos.x + widget.width;
        }
        else if(widget.pivot == UIWidget.Pivot.Right || widget.pivot == UIWidget.Pivot.BottomRight || widget.pivot == UIWidget.Pivot.TopRight)
        {
            minX = localPos.x - widget.width;
            maxX = localPos.x;
        }
        if (widget.pivot == UIWidget.Pivot.Bottom || widget.pivot == UIWidget.Pivot.BottomLeft || widget.pivot == UIWidget.Pivot.BottomRight)
        {
            minY = localPos.y;
            maxY = localPos.y + widget.height;
        }
        else if (widget.pivot == UIWidget.Pivot.Top || widget.pivot == UIWidget.Pivot.TopLeft || widget.pivot == UIWidget.Pivot.TopRight)
        {
            minY = localPos.y - widget.height;
            maxY = localPos.y;
        }
        if (mousePos.x < maxX && mousePos.x > minX && mousePos.y < maxY && mousePos.y > minY)
            return true;
        return false;
    }
}

总体思路:去掉背景点击BoxCollider,改由触摸事件来关闭界面;这样就可以达到关闭界面的同时触发下一层的功能的目的;

这个方法有缺陷:因为基于触摸事件所以当此界面上层有覆盖界面时依然会执行逻辑;对此可能加入UIPanel的depth进行判断;不知道还有什么好的解决方法!待完善

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity基于NGUI点击事件向下传递的解决方法 的相关文章

  • UE4 解决景深效果闪烁问题

    原因 1 模型的垂直竖线 造成抗锯齿算法对竖线的渲染计算 处于一种不稳定的状态 因此闪烁 解决办法 使用LOD 用贴图去替代线条模型 2 材质的法线贴图 当法线贴图含有垂直竖线的纹理效果 也会造成闪烁 比如这种幕墙材质 解决办法 关闭或动态
  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • Unity 粒子特效、材质发光 HDR ShaderGraph图文教程[完成lit发光设置]

    效果如图 准备工作 在hdr模式下 关闭Directional Light 相机设置 移动球挂一个点光源作为子节点 设置自行调节 0 创建移动球的材质及shader shader gt 在Project Create Shader Grap
  • Unity动画控制器animator.CrossFade

    需要特别注意 1 CrossFade虽然可以不用任何逻辑来链接而直接跳转 但是CrossFade只能覆盖其他动画 当当前动画播放完毕而没有跳出这个动画时再次调用CrossFade将会失败 造成动画依旧停在原位 参数animator Cros
  • Unity中按钮检测鼠标状态

    改方法主要是用于按钮检测鼠标的进入 滑出 点击 抬起 长按 长按停止 1 先将下面这个脚本挂载到需要检测鼠标状态的按钮上 using System Collections using System Collections Generic u
  • UnityVR--组件3--Line Renderer--线性渲染

    目录 线性渲染组件简介 绘制线条Line Renderer组件介绍 绘制拖尾Trail Renderer组件介绍 应用1 使用Line Renderer绘制线段 应用1实现 使用系统工具或自定义工具绘制线段 应用2 Trail Render
  • Unity3d 插件 系列——DoTweenPro介绍(图文详细+案例)

    Unity3d 插件 系列 DoTweenPro介绍 图文详细 案例 前言 一 DoTweenPro简介 二 DoTweenPro安装 三 DoTweenPro主要组件 1 DoTweenAnimation 2 DoTweenPath 3
  • Unity与Android的Back键冲突解决

    Unity与Android的Back键冲突解决 上一篇的最后留下了两个问题 Unity视图下横屏闪退 Unity视图下Android无法响应back返回上一activity 对于第一个问题 应该是Unity横屏下视图的某些设置跟Androi
  • 【IMGUI】 各种辅助类 EditorGUIUtility、EditorUtility、GUIUtility、GUILayoutUtility

    EditorGUIUtility class in Editor 继承自 GUIUtility EditorGUI 的各种辅助程序 EditorGUIUtility currentViewWidth 我尝试打印了下这个值和position
  • 【Unity】按Esc进入操作菜单

    本文章是基于如下视频的自我总结 https www youtube com watch v JivuXdrIHK0 步骤如下 1 在Canvas 界面添加一个Panel Panel中添加一个按钮 调整按钮的大小为合适大小 调整字体的大小为合
  • 【Unity步步升】监控与检测物体的各种方案,如:射线、碰撞、挂载等...

    在制作AR模型数值控制方案的时候遇到了检测的问题 学习过程受益匪浅 故今天为大家整理带来一篇监控与检测物体的参考方案集合 目录 一 射线检测 二 物体存在检测 三 碰撞检测 一 射线检测 单射线检测 首先完成搭建场景如下图1 1 我这里用到
  • unity3d 自定义的图片无法放入source image中

    须将图片的texture type改为 sprite
  • 【原神游戏开发日志1】缘起

    原神游戏开发日志1 缘起 版权声明 本文为 优梦创客 原创文章 您可以自由转载 但必须加入完整的版权声明 文章内容不得删减 修改 演绎 相关学习资源见文末 大家好 最近看到原神在TGA上频频获奖 作为一个14年经验的游戏开发行业的老兵 我就
  • unity小球跟随音乐节奏放大缩小和改变颜色

    放在小球身上 设置对应组件即可 using System Collections using System Collections Generic using Unity VisualScripting using UnityEngine
  • Unity学习笔记

    一 旋转欧拉角 四元数 Vector3 rotate new Vector3 0 30 0 Quaternion quaternion Quaternion identity quaternion Quaternion Euler rota
  • U3D游戏开发中摇杆的制作(UGUI版)

    在PC端模拟摇杆 实现玩家通过控制摇杆让玩家移动 以下是完整代码 using System Collections using System Collections Generic using UnityEngine using Unity
  • 游戏开发常见操作梳理之NPC任务系统

    多数游戏存在任务系统 接下来介绍通过NPC触发任务的游戏制作代码 using System Collections using System Collections Generic using UnityEngine
  • 游戏开发创建操作之玩家信息系统的建立

    游戏一般都需要玩家信息系统 那么我们应该如何搭建玩家信息系统 接下来我将展示一种简单的方法 完整代码如下 using System Collections using System Collections Generic using Uni
  • 游戏开发常见操作梳理之角色选择一

    进入游戏后 我们经常会进入角色选择的界面 通常是左右两个按钮可以更改角色供玩家选择 对于这种界面我们通常使用数据持久化将角色信息存储起来 接下来的笔记中 我将使用自带的数据持久化系统对其进行操作 实现角色的选择页面 后续会更新xml系列的文
  • 游戏开发中常见系统梳理之背包系统的实现一

    游戏中几乎都存在大大小小的背包系统 接下来我将讲述背包系统具体是如何实现的 完整源码 以下是使用unity NGUI实现 使用txt配置的方法 后续更新UGUI Json实现的背包系统敬请期待 背包中的物品我们常常将其制作成预设体 通过改变

随机推荐

  • jupyter中图片显示

    文章目录 jupyter notebook中图片显示 1 html方式 2 PIL图片显示 3 opencv图片显示 4 Ipython 方式 jupyter notebook中图片显示 以下用多种方式 其中第一种和第四种方便查看图片 代码
  • chmod命令原理及用法详解

    Chmod命令主要用于修改 设置文件权限 chmod 修改文件权限主要有两种方式 字母法与数字法 虽然数字法相对字母法简单 但是数字法是基于字母法 所以这里先介绍字母法 1 字母法 chmod u g o a r w x 文件名 以上是ch
  • Linux-应用编程-学习总结(3):进程间通信(上)

    Linux 应用编程 学习总结 3 进程间通信 上 前言 进程间通信相关概念 管道 管道的概念 管道的原理 管道的局限性 创建匿名管道 fifo 有名管道 特点 使用场景 创建方式 内存映射区 前言 这次对进程间通信进行总结 上一篇文章以及
  • 微信开放平台【第三方平台】java开发总结:预授权码(pre_auth_code)(三)

    微信第三方平台预授权码 pre auth code 开发说明 全网最详细的微信第三方平台预授权码开发说明 预授权码 预授权码 pre auth code 是第三方平台方实现授权托管的必备信息 每个预授权码有效期为 10 分钟 需要先获取令牌
  • XMPP客户端库Smack 4.1.4版官方开发文档之二

    本文转载自 博客主页 http blog csdn net chszs 三 Smack库的组成 Smack库可以内嵌到任意的Java应用程序中 Smack库有数个JAR文件组成 非常具有灵活性 1 smack core jar 提供了核心X
  • 这是mybatis最简单的入门

    这里有一个demo 这是mybatis最简单的入门 使用的IDE为idea 是maven的哦 这篇只是很简单的一个查询demo 目标是ssm 先来pom文件 这个不知道在网上哪里找的 lt gt
  • 自定义限制接口访问次数(ExpiringMap)

    ExpiringMap简介 它具有高性能 低开销 零依赖 线程安全 使用ConcurrentMa的实现过期entries等优点 主要特点包括 过期策略 可变有效期 最大尺寸 侦听器过期 延迟输入加载 过期自省 可设置Map中的Entry在一
  • python opencv旋转,Python OpenCV cv2.rotate()用法及代码示例

    OpenCV Python是旨在解决计算机视觉问题的Python绑定库 cv2 rotate 方法用于将2D数组旋转90度的倍数 函数cv rotate以三种不同的方式旋转数组 用法 cv2 cv rotate src rotateCode
  • Pandas 三大对象

    1 pandas的Series对象 pandas的Series对象是一个带索引数据构成的一维数组 可以用一个数组创建Series对象 import pandas as pd data pd Series 0 25 0 5 0 75 1 0
  • 为你的嵌入式设计选择合适的低功耗处理器

    在早期 获得低功耗的CPU通常意味着牺牲功能 以降低的时钟速度运行或等待新的低功耗处理技术以降低待机 和有功功耗 无论如何 情况已不再如此 并且处理器领域已经发生了戏剧性的变化 随着处理技术的进步以及创新的芯片设计和高粒度电源管理软件 带来
  • Python2.7.16安装(Ubuntu16.04)

    Python2 7 16安装 Ubuntu16 04 前面的文章已经介绍了在Windows上安装Python2和Python3了 现在介绍Linux系统上的安装 Ubuntu16 04上默认安装了Python2 7和Python3 5 Re
  • HTML 文件中引入高德地图

    准备工作 1 在高德开放平台 注册开发者账号 2 登陆之后 进入 应用管理 点击 我的应用 选择右上角 创建新应用 3 为应用添加 Key 在 服务平台 一项选择 Web 端 JSAPI 页面实现 1 创建一个div 作为地图的容器 2 设
  • Week2:包含 min 函数的栈

    1 题目描述 定义栈的数据结构 请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中 调用 min push 及 pop 的时间复杂度都是 O 1 示例 MinStack minStack new MinStack minSta
  • Vue下OpenLayers中Style-Icon的图片路径

    OpenLayers加载图片的方式 1 使用 require 方式加载图片 图片路径 根目录 src assets let styles icon new Style image new Icon anchor 0 5 1 src requ
  • 解决阿里云无法正常使用samba的问题

    昨天在阿里云上申请了一个云服务器 系统用的是ubuntu14 04 由于是免费的 初次使用 配置较低 单核1G内存 40G硬盘 所以在服务器上不方便安装图形界面 默认的系统镜像是没有桌面系统的 毕竟只是服务器 没有图形界面总觉得不是很方便
  • TensorFlow2.0学习笔记-3.模型训练

    3 模型训练 3 1 Keras版本模型训练 构建模型 顺序模型 函数式模型 子类模型 模型训练 model fit 模型验证 model evaluate 模型预测 model predict 使用样本加权和类别加权 回调函数 Model
  • 二叉树树叶与度为2的节点数关系论证

    如果二叉树树叶总数为n0 度为2的节点总数为n2 那么有n0 n2 1 下面论证这一关系 假设树叶总数为0 度为1的节点总数为n1 度为二的节点总数为n2 那么二叉树总结点数n满足以下关系 n n0 n1 n2 另一方面 除根节点以外的所有
  • CentOS下7zip包的解压、压缩方法

    1 安装7z 1 直接安装 yum install p7zip 2 源代码下载编译 wget http sourceforge net projects p7zip 9 13 p7zip 9 13 src all tar bz2 downl
  • ESP32通过UART串口使用AT指令

    ESP32通过UART串口使用AT指令 MCU起航 mcublog cn ESP32通过UART串口使用AT指令 MCU起航 mcublog cn
  • Unity基于NGUI点击事件向下传递的解决方法

    Unity开发中经常有点击Button 弹窗提示界面 然后点击任意区域关闭提示界面并且提示界面下一层的事件依然可以触发 需要点击事件向下传递 UGUI对此支持相对好处理 NGUI本身对此支持不好 这里提供一个方法 public class