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版本。在这个版本上做了些测试。得到以下数据:

  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处理的核心代码。

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

时间: 2024-08-27 01:27:45

unity ugui消息透传的相关文章

环信透传消息,无法回调

震 [[EMClient sharedClient].chatManager sendMessageReadAck:msg completion:^(EMMessage *aMessage, EMError *aError) { BSLog(@"----%@---%@---", aMessage, aError); }]; [[EMClient sharedClient].chatManager sendMessage:msg progress:^(int progress) { }

「ZigBee模块」协议栈-串口透传,打造无线串口模块

前面写比较仔细,后面一个么因为和前面重复了,不多说了,还有个原因...我懒...O(∩_∩)O哈哈~ 串口透传,打造无线串口模块 一.实验目的 两台PC机各使用串口连接一个zigbee模块,连接正确后打开串口调试助手发送信息.利用zigbee将从串口接收到的数据无线传送给另一个zigbee模块,另一个zigbee模块通过串口将数据传给PC端并在屏幕上显示. 二.实验平台 硬件:两个zigbee模块,两台PC机(其实一台也许,连接不同串口即可),编译器,方口转USB数据线两根 软件:基于Z-sta

视频流网络透传分析

最近在翻看以前写的文档,把这篇word文档复制下来,保留一下. 序号 版本 作者 描述 1 V0.1 YJ.Yan 初始版本 2 V0.2 YJ.Yan 添加方案细节描述以及可参考方案 1.      基本概念 a)       NAT 网络地址转换(NAT,Network AddressTranslation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中.原因很简单,NAT不仅完美地解决了IP

推送、透传、MQ

推送: 网页推送,是指将经过整理的信息资源以网页的形式迅速转发至用户的界面,实现用户的多层次需求,使得用户能够自己设定所需要的信息频道,并直接在用户端接收定制信息的实现方式. 推送功能:在手机通信中,大多智能机都支持推送功能.比如,你手机上有一个即时消息软件,当它在运行时它是和服务器相连的:但是一旦退出后,你就失去了连接.这时推送服务就开始工作了. 程序后台运行时都将会采用这样的一种提醒方式,比如提醒你升级,实时更新消息等. 官方的解释:所谓信息推送,就是"web广播",是通过一定的技

Dubbo透传traceId/logid的一种思路

前言: 随着dubbo的开源, 以及成为apache顶级项目. dubbo越来越受到国内java developer欢迎, 甚至成为服务化自治的首选方案. 随着微服务的流行, 如何跟踪整个调用链, 成了一个课题. 大家能够达成一致的思路, 在调用中添加traceId/logid信息, 至于如何实现, 各家都有自己的思路. 本文将对比几种方案, 重点讲解利用dubbo的自定义filter的机制, 来实现traceId/logid的透传. 方案一: 这个方案也是最直接的方法, 正如所谓所见即所得,

SIM800L透传模式配置

UART1_SendString("AT+CIPCLOSE=1"); //关闭连接 delay_ms(100); Second_AT_Command("AT+CIPSHUT","SHUT OK",2); //关闭移动场景 Second_AT_Command("AT+CGCLASS=\"B\"","OK",2);//设置GPRS移动台类别为B,支持包交换和数据交换 Second_AT_Co

Unity UGUI —— 无限循环List

还记得大学毕业刚工作的时候是做flash的开发,那时候看到别人写的各种各样的UI组件就非常佩服,后来自己也慢慢尝试着写,发现其实也就那么回事.UI的开发其实技术的成分相对来说不算多,但是一个好的UI是绝对少不了底层组件的支持的.我个人认为UI组件中相对比较复杂的就是List了,所以,这两天实现了一个UGUI的list,写了好几个版本,最终这个版本是相对比较好用的,在这我介绍一下大概思路,一是巩固一下知识做个记录,二是发扬一下分享精神.嘿嘿,大家多多赐教. 写List有两个重点是需要考虑的: 1.

二层透传介绍

二层协议透明传输的基本原理 工作流程 1.在骨干网的用户接入侧替换原始二层协议报文的组播目的MAC地址为特定的组播MAC地址.(修改源组播MAC地址) 2.修改MAC地址后的报文在骨干网中根据配置的透明传输方式决定是否对报文进行处理.(查看骨干网透传规则) 3.当该二层协议报文到达出节点时,通过匹配设备上配置的特殊组播目的MAC和二层协议的映射关系,将报文的组播目的MAC还原成该二层协议标准的组播目的MAC地址,并根据配置的透明传输方式决定是否处理该报文.(转换找出映射关系,还原组播MAC地址,

CC1101 433无线模块,STM8串口透传

CC1101 433无线模块,STM8串口透传 原理图:http://download.csdn.net/detail/cp1300/7496509 下面是STM8程序 CC1101.C [cpp] view plaincopy /************************************************************************************************************* * 文件名: CC1101.c * 功能:  S