公司要做一个这东西。

A是滑动区域,ScrollRect组件。

B是各种选项。

C是拾取到鼠标(或触点)的选项。

D是拖放区域。

大概要求是这样。

因为B的条目很多,放在A里可以滑动查看。如果要选择一个B,需要长按B,待时间足够之后生产一个新的C。拖动到D区域释放,则给D添加一个节点。其他区域则取消。

如果按住B的时间不够长,又动了鼠标(或触点),则当前滑动操作由A响应,产生A的滑动效果。

这里涉及到一个消息透传的问题。

解释一下自己在做的过程中采用的2个方案以及各自问题。

涉及的函数有以下几个:

OnPointerDown

OnPointerUp

OnDrag

将最终结果放这里,你要不愿看完,直接拿东西走人。

消息重置代码。

		eventData.pointerEnter = m_Scro.gameObject;
eventData.pointerPress = m_Scro.gameObject;
eventData.rawPointerPress = m_Scro.gameObject;
eventData.pointerDrag = m_Scro.gameObject;
m_Scro.OnBeginDrag(eventData);

方案1:

win7+unity531。

刚开做的时候使用的531版本。在这个版本上做了些测试。得到以下数据:

  1. 使用EventTrigger,只有最上面的ui可以获得输入并调用EventTrigger设置的函数。
  2. 如果不使用EventTrigger,则需要自己继承一些类。需要什么类可以在EventTrigger里根据你需要的函数进行查询。比如你在EventTrigger中使用了Pointer Up消息。直接在unity文档的脚本分类下查询pointerup即可找到这个消息由哪个类分发,继承一下,自己重写一下这个函数就好。
  3. 如果不使用EventTrigger,采用继承消息类的方式工作,那么UI是否响应输入由Raycast Target这个选项决定。(使用EventTrigger的情况下没测,因为那个满足不了需求了。)
  4. 当你对一个Ui进行了操作之后,如果不做任何修改和特别处理,默认情况下,所有鼠标(或触点)操作均由这个UI控件接收。比如先在这个控件内OnPointerDown,然后按住鼠标不放,鼠标移动到别的Ui上,再放开,OnPointerUp函数依旧调用的是OnPointerDown时的UI。
  5. 如果只继承了OnPointerDown和OnPointerUp函数。则当OnPointerDown进入之后,如果产生了Drag输入,则会产生OnPointerUp事件。
  6. 再使用继承消息类及以上信息的情况下,A可以在即使点中B的情况下正常拖动。而且B的函数照进。
  7. 拖放操作响应函数是OnDrop,遵循第四条规则。但是如果我希望别的控件能够响应OnDrop,只需要把当前移动的这个UI的Raycast Target设置为false就好。(这里其实已经是一种消息透传了)

根据以上信息,于是我做了第一套方案:

大致如下:

  • 当我按下B时,开启一个协程(等待1s,为长按时间)。如果协程没处理之前进入了OnPointerUp,则销毁协程。成功,则产生一个C,并将A设置enable为false,防止我在移动C的时候A跟着动。
  • 生成的C交给一个全局管理器,这个管理器有一个m_Drag的GameObject对象。当该对象不为空,则在Update里帧更新这个对象的位置。用这个方法来实现拖动。
  • 然后给D设置一个OnDrop函数。如果OnDrop函数调用,则通知全局管理器,C已被获取,清理。
  • 全局管理器要判定一下,如果已经没有触点(使用Input.GetMouseButton(0)函数可以满足这个需求,虽然有意外情况,但至少正向流程OK),则销毁m_Drag

根据以上思路,大部分情况都解决了。只是有一个问题。全局管理器的触点判定是在Update里的。而OnDrop是触发的。逻辑是OnDrop响应之后做自身的处理,并通知全局管理器清空m_Drag一防止被Destroy。但并不知道当前这次的消息处理是在Update之前还是之后。如果在当前帧,鼠标触点已经释放,先进入Update,则在OnDrop被触发之前,m_Drag就会被Update先给Destroy掉。而如果OnDrop先调用,则可以确保正常。

在531下,测试结果显示,当前帧的输入处理在Update之前,于是方案一完成。

合并代码,对方用的535,于是我只好跟着升,这一升,坏了。拖动出问题了,拖出来放不进去了。

一检查,OnDrop跑到Update后面执行去了。

这样一来,没有合适的地方可以判断鼠标(或触点)的释放。于是只好考虑用OnPointerUp好了。可是OnPointerUp在控件被拖动的时候就会调用啊,根本没有机会或者说合适的地方可以产生OnPointerUp函数的调用,于是又做了一些测试如下:

  1. 如果只继承了OnPointerDown和OnPointerUp函数。则当OnPointerDown进入之后,如果产生了Drag输入,则会产生OnPointerUp事件。但如果再继承OnDrag,则会进入OnDrag事件而不是OnPointerUp。OnPointerUp将会在鼠标弹起(或触点被释放)时产生。

这是方案一第五条的补充。也是加入OnDrag之后逐步发现的,中间也调试了很久,出了很多麻烦事情。

有了这条,似乎一切都没问题了。于是加上,测试,一切OK。似乎完成了。然后我发现A在点到B的时候不再获取输入了。也就是说当我点到B的时候,A不能被滑动。Drag消息传给了B的脚本。

注:到这一步,我并没有尝试用关闭Raycast Target的方法来解决。原因有2:

  1. 我需要OnPointerUp,如果关闭,OnPointerUp想来是不会响应的,因为如果能通过关闭Raycast Target来将Drag传给A,那说明B已经不再获取输入了。
  2. 我需要彻底解决消息透传的问题,万一还有其他模块也会遇到类似的情况呢?

于是无法避免,考虑到以后也可能要用,只好来硬的,一定要解决消息透传的问题。

现在思路有2:

  1. 获取到我要控制的组件,在当前UI内,将输入信息传给这个要控制的组件,再修改。(这里就是在B内获取到Drag信息,将Drag信息传递给A对象,以控制A的滑动)
  2. 将输入消息重置。或新建一个,或将我希望获取输入的组件放进去。

翻了好久。EventSystem、BaseEventData、PointerEventData都翻过了,没有发现。

于是采用第一条思路。第一条思路也很容易。也许用在别的ui上已经没问题了。

但最让我伤心的是ScrollRect这个组件,如果你通过外部的方式(就是直接脚本改坐标)修改其容器的坐标,会弹回去。于是又去查怎么取消ScrollRect的回弹操作。一系列处理下来,似乎也能满足要求。然而因为第一次使用ugui,并没有发现有什么好的方案能让我在消息透传的时候让ScrollRect不弹回,而当我消息透传结束之后再开启弹回。就算有,界面上的小跳动,也无法直视。

于是又想。还是再看看,再嗖嗖,看看能不能重置消息。毕竟这才是正道。

然后解开了。怎么发现的我就不说了,纯属运气。我在查看EventSystem这个场景对象的时候,发现有个pointerDrag的对象。正好是我拖动的对象,我在想,如果改掉他会怎么样?

于是脚本里一搜pointerDrag,在PointerEventData类下。这就是消息函数传进来的参数啊。于是将pointerDrag直接改成了A,好的,一切工作正常,就是还会跳动。推测可能是因为中途突然加入输入信息导致,没有前提条件。于是将ScrollRect的Drag函数查询了一番,正好有个OnBeginDrag,加上,一切就正常了。

		eventData.pointerEnter = m_Scro.gameObject;
eventData.pointerPress = m_Scro.gameObject;
eventData.rawPointerPress = m_Scro.gameObject;
eventData.pointerDrag = m_Scro.gameObject;
m_Scro.OnBeginDrag(eventData);

这就是消息重置。

就是当按住B的时间不够,产生了拖动,要将当前拖动消息交由A处理的核心代码。

其他消息相信也应该类似。

unity ugui消息透传的更多相关文章

  1. 个推+DCLOUD,推送消息和透传消息

    DCLOUD方案中集成了个推方案,最好是用个推来做推送相关的东西 消息分2类: 1.推送消息,这种一般会出现在手机的最上面的通知栏,用户是肯定会知道的 2.透传消息,这种一般就是一个Alert提示框, ...

  2. APP消息推送:通知和透传

    目前市场上的消息推送方式有两种:通知和透传.什么是透传?透传即是透明传送,即传送网络无论传输业务如何,只负责将需要传送的业务传送到目的节点,同时保证传输的质量即可,而不对传输的业务进行处理.透传消息, ...

  3. iOS 环信透传cmd消息多次重复接收,解决办法

    由于项目需求,需要在项目中接到消息的时候做不同界面的不同的操作,哪儿需要哪儿就要添加代理:引起代理事件重复执行:所以要在VC显示的时候添加代理,消失的时候删除代理 环信 透传 消息多次接收情况(由于代 ...

  4. ESP8266串口和MQTT服务器消息互传(版本一) 单纯透传+保存WIFI账号信息

    目标 制作一个ESP8266串口和MQTT相互透传的小WIFI,可用手机修改其连接的路由器,由此该模块可以任意加载到各种串口传输的单片机上,完成硬件到云端的传输. 1 实物图 2 MQTT网页测试客户 ...

  5. iOS端给unity发送消息,实现两者交互。

    上一篇我们简单说了一下unity发消息给iOS端.现在我们就来说一下iOS端给unity发送消息的简单使用. 首先iOS端做得事情其实很简单就一句话,直接上代码 /** * 第一个参数:是unity那 ...

  6. Dubbo透传traceId/logid的一种思路

    前言: 随着dubbo的开源, 以及成为apache顶级项目. dubbo越来越受到国内java developer欢迎, 甚至成为服务化自治的首选方案. 随着微服务的流行, 如何跟踪整个调用链, 成 ...

  7. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(Wi-Fi模块AT指令TCP透传方式),MQTT通信控制升级

    实现功能概要 前面的版本都是,定时访问云端的程序版本,如果版本不一致,然后下载最新的升级文件,实现升级. 这一节,在用户程序里面加入MQTT通信,执行用户程序的时候,通过接收MQTT的升级命令实现升级 ...

  8. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于GPRS模块(Air202,SIM800)AT指令TCP透传方式,MQTT通信控制升级

    实现功能概要 这节和上一节的功能一样(只不过上节是利用Wi-Fi模块,这节是利用GPRS模块) 用户程序里面加入MQTT通信,执行用户程序的时候, 通过接收MQTT的升级命令实现升级. 凡是可以实现M ...

  9. 1、利用蓝牙定位及姿态识别实现一个智能篮球场套件(一)——用重写CC2541透传模块做成智能手环

    一.预言 要实现一个智能篮球场套件,需要设计一个佩戴在篮球运动员手臂上的可以检测投篮.记步的手环,以及一套可以根据RSSI定位运动员的蓝牙定位装置.下面是大致需要的步骤: 首先,需要用CC2541透传 ...

随机推荐

  1. C++ 学习笔记之 STL 队列

    一.  引言 在算法以及数据结构的实现中,很多地方我们都需要队列(遵循FIFO,先进先出原则). 为了使用队列,我们可以自己用数组来实现队列,但自己写太麻烦不说,并且还很容易出错. 好在C++的STL ...

  2. 网络编程--System.Net

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  3. 含html转义字符编码(四)转换--python

    在抓取下来的网页源码显示的是如下的内容,而不是可读性的汉字 (当然,如果是在Web页面上展示,则实体会自动被浏览器转为原字符,正常显示) 经查资料后得知, 在网页中以四开头的是HTML实体,具体什么是 ...

  4. Java中的日志——Java.util.logging、log4j、commons-logging

    Java中给项目程序添加log主要有三种方式,一使用JDK中的java.util.logging包,一种是log4j,一种是commons-logging.其中log4j和commons-loggin ...

  5. [剑指Offer] 45.扑克牌顺子

    题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决 ...

  6. Delphi SQL语句字符串拼接

    单引号必须成对出现,最外层的单引号表示其内部符号为字符:除最外层以外的单引号,每两个单引号代表一个'字符.加号:+用于字符串之间的连接.字符串常量用四个单引号,例如 ' select * from T ...

  7. BZOJ4299 Codechef FRBSUM(主席树)

    感觉非常不可做,于是考虑有什么奇怪的性质. 先考虑怎么求子集和mex.将数从小到大排序,假设已经凑出了0~n的所有数,如果下一个数>n+1显然mex就是n+1了,否则若其为x则可以凑出1~n+x ...

  8. POJ1523:SPF——题解

    http://poj.org/problem?id=1523 这题明显就是求割点然后求割完之后的强连通分量的个数. 割点都会求,怎么求割完的分量个数呢? 我们可以通过万能的并查集啊!(具体做法看代码吧 ...

  9. 浴谷夏令营例题Codeforces827DBest Edge Weight(三个愿望,一次满足~(大雾

    这题在浴谷夏令营wyx在讲的最小生成树的时候提到过,但并没有细讲怎么写... 这题可以用三种写法写,虽然只有两种能过...(倍增/倍增+并查集/树链剖分 先跑出最小生成树,分类讨论,在MST上的边,考 ...

  10. ContestHunter暑假欢乐赛 SRM 01 - 儿童节常数赛 爆陵记

    最后15min过了两题...MDZZ 果然是不适合OI赛制啊...半场写完三题还自信满满的,还好有CZL报哪题错了嘿嘿嘿(这算不算犯规了(逃 悲惨的故事*1....如果没有CZL的话T1 10分 悲惨 ...