unity3d:UGUI源码EventSystem输入系统常见问题

本文详细探讨Unity中Button和Text组件的点击响应机制,重点讲解了EventSystem、Raycast、IPointerClickHandler和优化策略,包括不规则按钮处理、穿透UI点击及性能优化。适合了解Unity UI开发者阅读。

1. button从按下到响应的过程

1.先是EventSystem在Update中调用当前输入模块InputModules的Process方法处理所有的鼠标事件,
2.并且输入模块会调用RaycastAll来得到目标信息,
3.通过子物体未挂载IEventSystemHandler,再找父物体方式找到事件实际接收者并执行点击事件

2. button子物体text也勾选了RaycastTarget,为什么是响应button,而不是text

创建一个Button,那这个Button还包含了Text组件,如果text.RaycastTarget勾上
当鼠标点击的时候会调用GetEventHandler函数,
该函数的root参数其实是Text,发现text无IEventSystemHandler组件
但是会查找到它的父物体Button,发现有,然后调用Button的点击事件
核心问题:text缺少IEventSystemHandler
public class Button : Selectable, IPointerClickHandler, ISubmitHandler
public interface IPointerClickHandler : IEventSystemHandler

点击button,先响应text,再查找到button,handlerCount为0,说明无IPointerClickHandler组件
在这里插入图片描述

text加上EventTrigger,会响应text的点击事件,不会向上响应button
在这里插入图片描述

3. 如何强制让text点击,例如聊天系统点击超链接

text挂脚本实现IPointerClickHandler 接口OnPointerClick

4. 穿透UI点击问题

IsPointerOverGameObject是射线接触到的UI有RaycastTarget

        public override bool IsPointerOverGameObject(int pointerId)
        {
            var lastPointer = GetLastPointerEventData(pointerId);
            if (lastPointer != null)
                return lastPointer.pointerEnter != null;
            return false;
        }

if (Input.GetMouseButtonDown(0))
            {
                if (Application.isMobilePlatform && Input.touchCount > 0)
                {
                    for (int i = 0; i < Input.touchCount; i++)
                    {
                        if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(i).fingerId))
                        {
                            m_isClickUi = true;
                            break;
                        }
                    }
                }
                else if (EventSystem.current.IsPointerOverGameObject())
                {
                    m_isClickUi = true;
                }
            }
            

5. EventSystem功能

EventSystem会在Update中调用输入模块PointerInputModule的Process方法来处理输入消息
PointerInputModule会调用EventSystem中的RaycastAll方法进行射线检测
RaycastAll又会调用BastRaycaster的Raycast方法执行具体的射线检测操作,主要是获取被选中的目标信息。

6. 不规则按钮如何响应点击

Polygon Collider 2D

7. 设计建造系统:如何拖动屏幕不响应建筑点击,如何区分是点击建筑还是拖动建筑

物品点击与拖屏

8. GraphicRaycaster.BlockingObjects

不用的时候不勾选2d,3d,在update有性能消耗。默认是none

if (blockingObjects == BlockingObjects.ThreeD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast3D != null)
                    {
                        var hits = ReflectionMethodsCache.Singleton.raycast3DAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                            hitDistance = hits[0].distance;
                    }
                }

                if (blockingObjects == BlockingObjects.TwoD || blockingObjects == BlockingObjects.All)
                {
                    if (ReflectionMethodsCache.Singleton.raycast2D != null)
                    {
                        var hits = ReflectionMethodsCache.Singleton.getRayIntersectionAll(ray, distanceToClipPlane, (int)m_BlockingMask);
                        if (hits.Length > 0)
                            hitDistance = hits[0].distance;
                    }
                }

9. 有哪些优化

1.不需要点击事件的可以不勾选RaycastTarget
2.封装点击按钮带参数

using UnityEngine;
using System.Collections;
using UnityEngine.Events;
using UnityEngine.EventSystems;

public class ClickListener : MonoBehaviour, IPointerClickHandler, IPointerDownHandler,IPointerUpHandler
{
    public delegate void VoidDelegate(GameObject go);
    public VoidDelegate onClick;
    public VoidDelegate onPress;
    public VoidDelegate onNewGuideClick;

    static public ClickListener Get(GameObject go)
    {
        ClickListener listener = go.GetComponent<ClickListener>();
        if (listener == null) listener = go.AddComponent<ClickListener>();
        return listener;
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (onClick != null)
        {
            onClick(gameObject);
        }
    }
    bool ispress;
    public void OnPointerDown(PointerEventData eventData)
    {
        ispress = true;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        ispress = false;
    }

    void Update() {
        if (onPress != null && ispress)
            onPress(gameObject);
    }
}

概要:   DevCon 实用工具是一种命令行实用工具,可以替代设备管理器。使用 DevCon,您可以启用禁用、重新启动、更新、删除查询单个设备或一组设备。DevCon 提供与开发人员有关但无法在设备管理器中看到的信息。   您可以将 DevCon 用于 Windows 2000 、Windows XPWindows vista。不能将 Devcon 用于 Microsoft Windows 95、Windows 98、或 Windows Millennium Edition。   下载:http://download.microsoft.com/download/1/1/f/11f7dd10-272d-4cd2-896f-9ce67f3e0240/devcon.exe 用法及参数说明:   devcon.exe [-r] [-m:\\] [...]   -r 如果指定它,在命令完成后若需要则重新启动计算机。    是目标计算机的名称。    是将要执行的命令(如下所示)。   ... 是命令需要的一个或多个参数。   要获取关于某一特定命令的帮助,请键入:devcon.exe help   classfilter 允许修改类别筛选程序。   classes 列出所有设备安装类别。   disable 禁用与指定的硬件或实例 ID 匹配的设备。   driverfiles 列出针对设备安装的驱动程序文件。   drivernodes 列出设备的所有驱动程序节点。   enable 启用与指定的硬件或 实例 ID 匹配的设备。   find 查找与指定的硬件或 实例 ID 匹配的设备。   findall 查找设备,包括那些未显示的设备。   help 显示此信息。   hwids 列出设备的硬件 ID。   install 手动安装设备。   listclass 列出某一安装类别的所有设备。   reboot 重新启动本地计算机。   remove 删除与特定的硬件或 实例 ID 匹配的设备。   rescan 扫描以发现新的硬件。   resources 列出设备的硬件资源。   restart 重新启动与特定的硬件或 实例 ID 匹配的设备。   stack 列出预期的设备驱动程序堆栈。   status 列出设备的运行状态。   update 手动更新设备。   UpdateNI 手动更新设备,无用户提示   SetHwID 添加、删除更改根枚举设备的硬件 ID 的顺序。 示例:   devcon -m:\\test find pci\* 列出计算机 test 上的所有已知 PCI 设备。(通过使用 -m,您可以指定一个目标计算机。您必须使用“进程间通信”(IPC) 访问此计算机。)   devcon -r install Windows directory\Inf\Netloop.inf *MSLOOP 安装一个新的 Microsoft 环回适配器实例。这将创建一个新的根枚举设备节点,使用此节点您可以安装“虚拟设备”,如环回适配器。如果需要重新启动计算机,此命令还将以安静模式重启计算机。   devcon classes 列出所有已知的安装类别。输出结果包含短的未本地化的名称(例如,“USB”)描述性名称(例如,“通用串行总线控制器”)。 禁用启用网卡的步骤:   1.用devcon hwids PCI*命令得到所有以PCI开头的设备。这时会列出很多设备,那么哪个才是网卡对应的呢?   2.打开设备管理器,展开网络适配器,找到网卡的名称,然后记住到刚才得到的列表中找对应的Name,然后你会在下面看到好几个ID,随便挑一个就行   3.用devcon disable "PCI\VEN_11AB&DEV_4380&SUBSYS_301B17AA&REV_10"禁用网卡(启用的话讲disable换成enable就行了)   4.其实用PCI开头得到的几组设备中一般第一个就是网卡设备 sysdzw 16:01 2010-11-16
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四夕立羽

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值