标签:
公司要做一个这东西。
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版本。在这个版本上做了些测试。得到以下数据:
根据以上信息,于是我做了第一套方案:
大致如下:
根据以上思路,大部分情况都解决了。只是有一个问题。全局管理器的触点判定是在Update里的。而OnDrop是触发的。逻辑是OnDrop响应之后做自身的处理,并通知全局管理器清空m_Drag一防止被Destroy。但并不知道当前这次的消息处理是在Update之前还是之后。如果在当前帧,鼠标触点已经释放,先进入Update,则在OnDrop被触发之前,m_Drag就会被Update先给Destroy掉。而如果OnDrop先调用,则可以确保正常。
在531下,测试结果显示,当前帧的输入处理在Update之前,于是方案一完成。
合并代码,对方用的535,于是我只好跟着升,这一升,坏了。拖动出问题了,拖出来放不进去了。
一检查,OnDrop跑到Update后面执行去了。
这样一来,没有合适的地方可以判断鼠标(或触点)的释放。于是只好考虑用OnPointerUp好了。可是OnPointerUp在控件被拖动的时候就会调用啊,根本没有机会或者说合适的地方可以产生OnPointerUp函数的调用,于是又做了一些测试如下:
这是方案一第五条的补充。也是加入OnDrag之后逐步发现的,中间也调试了很久,出了很多麻烦事情。
有了这条,似乎一切都没问题了。于是加上,测试,一切OK。似乎完成了。然后我发现A在点到B的时候不再获取输入了。也就是说当我点到B的时候,A不能被滑动。Drag消息传给了B的脚本。
『
注:到这一步,我并没有尝试用关闭Raycast Target的方法来解决。原因有2:
』
于是无法避免,考虑到以后也可能要用,只好来硬的,一定要解决消息透传的问题。
现在思路有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处理的核心代码。
其他消息相信也应该类似。
标签:
原文地址:http://www.cnblogs.com/saucerman/p/5864512.html