unity ugui消息透传

公司要做一个这东西。
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版本。在这个版本上做了些测试。得到以下数据:
- 使用EventTrigger,只有最上面的ui可以获得输入并调用EventTrigger设置的函数。
- 如果不使用EventTrigger,则需要自己继承一些类。需要什么类可以在EventTrigger里根据你需要的函数进行查询。比如你在EventTrigger中使用了Pointer Up消息。直接在unity文档的脚本分类下查询pointerup即可找到这个消息由哪个类分发,继承一下,自己重写一下这个函数就好。
- 如果不使用EventTrigger,采用继承消息类的方式工作,那么UI是否响应输入由Raycast Target这个选项决定。(使用EventTrigger的情况下没测,因为那个满足不了需求了。)
- 当你对一个Ui进行了操作之后,如果不做任何修改和特别处理,默认情况下,所有鼠标(或触点)操作均由这个UI控件接收。比如先在这个控件内OnPointerDown,然后按住鼠标不放,鼠标移动到别的Ui上,再放开,OnPointerUp函数依旧调用的是OnPointerDown时的UI。
- 如果只继承了OnPointerDown和OnPointerUp函数。则当OnPointerDown进入之后,如果产生了Drag输入,则会产生OnPointerUp事件。
- 再使用继承消息类及以上信息的情况下,A可以在即使点中B的情况下正常拖动。而且B的函数照进。
- 拖放操作响应函数是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函数的调用,于是又做了一些测试如下:
- 如果只继承了OnPointerDown和OnPointerUp函数。则当OnPointerDown进入之后,如果产生了Drag输入,则会产生OnPointerUp事件。但如果再继承OnDrag,则会进入OnDrag事件而不是OnPointerUp。OnPointerUp将会在鼠标弹起(或触点被释放)时产生。
这是方案一第五条的补充。也是加入OnDrag之后逐步发现的,中间也调试了很久,出了很多麻烦事情。
有了这条,似乎一切都没问题了。于是加上,测试,一切OK。似乎完成了。然后我发现A在点到B的时候不再获取输入了。也就是说当我点到B的时候,A不能被滑动。Drag消息传给了B的脚本。
『
注:到这一步,我并没有尝试用关闭Raycast Target的方法来解决。原因有2:
- 我需要OnPointerUp,如果关闭,OnPointerUp想来是不会响应的,因为如果能通过关闭Raycast Target来将Drag传给A,那说明B已经不再获取输入了。
- 我需要彻底解决消息透传的问题,万一还有其他模块也会遇到类似的情况呢?
』
于是无法避免,考虑到以后也可能要用,只好来硬的,一定要解决消息透传的问题。
现在思路有2:
- 获取到我要控制的组件,在当前UI内,将输入信息传给这个要控制的组件,再修改。(这里就是在B内获取到Drag信息,将Drag信息传递给A对象,以控制A的滑动)
- 将输入消息重置。或新建一个,或将我希望获取输入的组件放进去。
翻了好久。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消息透传的更多相关文章
- 个推+DCLOUD,推送消息和透传消息
DCLOUD方案中集成了个推方案,最好是用个推来做推送相关的东西 消息分2类: 1.推送消息,这种一般会出现在手机的最上面的通知栏,用户是肯定会知道的 2.透传消息,这种一般就是一个Alert提示框, ...
- APP消息推送:通知和透传
目前市场上的消息推送方式有两种:通知和透传.什么是透传?透传即是透明传送,即传送网络无论传输业务如何,只负责将需要传送的业务传送到目的节点,同时保证传输的质量即可,而不对传输的业务进行处理.透传消息, ...
- iOS 环信透传cmd消息多次重复接收,解决办法
由于项目需求,需要在项目中接到消息的时候做不同界面的不同的操作,哪儿需要哪儿就要添加代理:引起代理事件重复执行:所以要在VC显示的时候添加代理,消失的时候删除代理 环信 透传 消息多次接收情况(由于代 ...
- ESP8266串口和MQTT服务器消息互传(版本一) 单纯透传+保存WIFI账号信息
目标 制作一个ESP8266串口和MQTT相互透传的小WIFI,可用手机修改其连接的路由器,由此该模块可以任意加载到各种串口传输的单片机上,完成硬件到云端的传输. 1 实物图 2 MQTT网页测试客户 ...
- iOS端给unity发送消息,实现两者交互。
上一篇我们简单说了一下unity发消息给iOS端.现在我们就来说一下iOS端给unity发送消息的简单使用. 首先iOS端做得事情其实很简单就一句话,直接上代码 /** * 第一个参数:是unity那 ...
- Dubbo透传traceId/logid的一种思路
前言: 随着dubbo的开源, 以及成为apache顶级项目. dubbo越来越受到国内java developer欢迎, 甚至成为服务化自治的首选方案. 随着微服务的流行, 如何跟踪整个调用链, 成 ...
- ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(Wi-Fi模块AT指令TCP透传方式),MQTT通信控制升级
实现功能概要 前面的版本都是,定时访问云端的程序版本,如果版本不一致,然后下载最新的升级文件,实现升级. 这一节,在用户程序里面加入MQTT通信,执行用户程序的时候,通过接收MQTT的升级命令实现升级 ...
- ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于GPRS模块(Air202,SIM800)AT指令TCP透传方式,MQTT通信控制升级
实现功能概要 这节和上一节的功能一样(只不过上节是利用Wi-Fi模块,这节是利用GPRS模块) 用户程序里面加入MQTT通信,执行用户程序的时候, 通过接收MQTT的升级命令实现升级. 凡是可以实现M ...
- 1、利用蓝牙定位及姿态识别实现一个智能篮球场套件(一)——用重写CC2541透传模块做成智能手环
一.预言 要实现一个智能篮球场套件,需要设计一个佩戴在篮球运动员手臂上的可以检测投篮.记步的手环,以及一套可以根据RSSI定位运动员的蓝牙定位装置.下面是大致需要的步骤: 首先,需要用CC2541透传 ...
随机推荐
- Alpha发布文案加美工展示
目录 团队简介 项目进展 组内分工 队员总结 后期计划 一.团队简介 二.项目进展 从选题发布到今天的Alpha发布,我们团队经历了许许多多的磨难.我们最终设计了如下的功能:首页.班级.个人.更多.打 ...
- Thunder团队第一周 - Scrum会议4
Scrum会议4 小组名称:Thunder 项目名称:爱阅app Scrum Master:代秋彤 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传 ...
- Linux GCC编译
.a 静态库(打包文件 由多个.o文件打包而成) .c 未经过预处理的C源码 .h C头文件 .i 经过预处理的C源码(将头文件内容加载到c文件中) .o 编译之后产生的目标文件 .s 生成的汇编语言 ...
- 1001 Duplicate Pair
1.题目戳这里 2.代码: #include<stdio.h> #include<string.h> int main() { int n; while(scanf(" ...
- 将MathType公式转换为LaTex格式
LaTex编辑公式不够直观,常常会因为结构复杂导致数据或者符号出错,使用MathType编辑公式后再直接转换成LaTex代码可以避免这个问题. 一.首先在MathType中编辑公式 二.然后点击参数— ...
- LintCode-71.二叉树的锯齿形层次遍历
二叉树的锯齿形层次遍历 给出一棵二叉树,返回其节点值的锯齿形层次遍历(先从左往右,下一层再从右往左,层与层之间交替进行) 样例 给出一棵二叉树 {3,9,20,#,#,15,7}, 返回其锯齿形的层次 ...
- Window Classes in Win32
探索Win32系统之窗口类(Window Classes in Win32) Kyle MarshMicrosoft Developer Network Technology GroupMSDN技术组 ...
- python 中的queue 与多进程--待继续
一.先说说Queue(队列对象) Queue是python中的标准库,可以直接import 引用,之前学习的时候有听过著名的“先吃先拉”与“后吃先吐”,其实就是这里说的队列,队列的构造的时候可以定义它 ...
- 【刷题】BZOJ 1717 [Usaco2006 Dec]Milk Patterns 产奶的模式
Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". ...
- CF#67 75d Big Maximum Sum
~~~题面~~~ 题解: 观察到拼接后的数据范围过大,无法O(n)解决,但是大区间是由很多小区间组成,而小区间是固定的,不会变化,所以可以考虑预处理出每个小区间的信息,然后根据给定序列按顺序一步一步合 ...