Unity UGuivue 拖拽组件碰撞

UGUI 背包-物品信息显示和拖拽功能的实现 - 简书
UGUI 背包-物品信息显示和拖拽功能的实现
物品信息显示和拖拽功能的实现
数据类都做好以后信息我们开始实现当我们的鼠标停放在物品上信息其信息的功能。(也就是提示框)
由于引入到格子的数据字典类。
更改脚本:
Paste_Image.png
首先我们先进行提示框UI设计的实现。创建一个Image并其添加Text作为文字的显示。设置Image的color的Alpha通道使其透明。
Paste_Image.png
我们应该使提示框根据需要显示文字的多少相应的生成多大,这里我们需要使用一些小技巧。我们设置好Anchors以后,复制一份Text,并将其拖拽出来将Image和Text作为其子物体。(这样当Text(1)大小改变时它的子物体都会跟着它动态的改变,但是Text(1)和Text的文字显示的不一样会造成缺陷,所以我们在显示信息时需要将Text(1)显示的文字同Text一样)
Paste_Image.png
为了实现根据文字的多少自适应大小,我们为这个Text(1)添加ContentSizeFilter内容大小的过滤器组件。并将水平和垂直的Fit都设置为Preferred Size(与文字相对应)
Paste_Image.png
根据文字的多少对应的显示。为了使它显示在鼠标的右下方,我们将其的Pivot轴中心设置在左上方。
Paste_Image.png
为它添加TooltipsUI脚本进行管理其隐藏和显示,以及文本赋值功能。
Paste_Image.png
获取两个Text中的文本显示
Paste_Image.png
由于获取格子中物品的信息是在每个格子中获取的,所以我们为我们的Grid的预设添加一个GridUI进行控制,为了实现当鼠标进入和移走时,这里我们让GridUI实现IPointerEnterHandler和IPointerExitHandler两个接口的OnPointerEnter和OnPointerExit方法。使在格子上能对鼠标的进入和移走进行检测。
为了进一步的实现,我们这里定义两个委托来对应相应事件的触发。
Paste_Image.png
Paste_Image.png
在Manager脚本中定义两个回调方法与委托相对应并注册。
Paste_Image.png
定义一个用于控制显示和隐藏的标志位isShow来控制。
Paste_Image.png
由于显示是杂乱无章的为了UI的美感,我们为我们的提示框信息的显示进行样式设计。定义一个方法用于Tooltip中的文字应该如何显示。(不同类型的物品有不同的属性)所以我们的需要用switch判断物品的类型是什么。
Paste_Image.png
通过之前已经做好的ItemModel数据类,来根据对应的格子取出对应的物品Item对象,并在两个回调方法中实现。
Paste_Image.png
Paste_Image.png
重点开始,那我们应该如何使其显示的位置与我们的鼠标相应了,这时就涉及到了坐标系之间的相互转换。(这时我们需要从屏幕坐标到UGUI坐标的转化。)
在Update中每帧检测位置。并进行屏幕坐标到UI坐标的转换。使用Unity工具类中的RectTransformUtility.ScreenPointToLocalPointInRectangle方法。
Paste_Image.png
通过API我们可以知道,它有四个参数:
第一个为RectTransform:我们每一个UGUI对象都具有这个组件,是它们在Canvas中的位置。这时我们需要得到的是在我们UI中的坐标,所以第一个参数自然就是Canvas的RectTransform。
第二个参数为screenPoint屏幕上的坐标,这时也就是我们的Input.MousePosition.
第三个参数为摄像机,由于我们的Canvas的Render Mode为Overlay是没有UI摄像机直接渲染在场景摄像机的最上方,所以这里也就是null。
第四个参数:out Vecter2 position,也就是通过这个方法得到的输出参数。
Paste_Image.png
知道了方法的原理,现在开始转换。
Paste_Image.png
为ToolTipsUI类提供一个SetLocalPosition方法,用于更新位置。
Paste_Image.png
在Manager脚本中的Update中实现。
Paste_Image.png
Paste_Image.png
拖拽功能的实现。
UGUI中的拖拽功能与NGUI中的不同,NGUI中的拖拽使用Drag脚本组件即可,而UGUI中需要实现IBeginDragHandler等句柄接口来进行实现。
知道了怎么可以实现拖拽,我们只需要分析拖拽的核心点就可以了,无非就是四种情况
拖拽到没有物品的格子中,将原有的格子中的物品删除,在新到达的格子中实例化这个Item。
拖拽到有物品的格子中(交换),将原有格子中的物品和当前到达格子的物品都删除,重新实例化这两个Item对象,在实例化的时候交换他们的父对象。(这里可以使用对象池提高性能)
拖拽到格子以外的地方但是还在背包的Panel中,视为拖拽失误回到原来的格子。
拖拽到格子以外的地方但是在背包的Panel之外,视为需要丢弃物品,直接删除物品对象即可。
将我们的ItemUI预设拖拽出,更名为DragItem,并为它添加一个全新的DragItemUI脚本进行控制,由于我们DragItem具有之前所有的ItemUI的功能,我们让其继承于ItemUI。并实现同TooltipUI脚本相同的功能。
Paste_Image.png
Paste_Image.png
由于拖拽也是对Grid中的子物体进行操作,所以我们在GridUI中使其实现IBeginDragHandler,IDragHandler,IEndDragHandler三个接口分别对应拖拽开始时,拖拽中,拖拽结束时所需要触发的事件。
Paste_Image.png
同Tooltips一样。我们也为它定义两个相应的事件委托:
OnLeftBeginDrag为当鼠标左键开始拖拽的事件,Transform参数代表拖拽出物品的格子的transform。
OnLeftEndDrag当鼠标左键结束拖拽的事件,第一个参数代表拖拽出物品的格子的transform,第二个Transform参数代表当前鼠标停留的格子的transform
Paste_Image.png
使用接口中的参数PointerEventData eventData,eventData.button来获取按下的键是什么,这里为鼠标左键。
Paste_Image.png
Paste_Image.png
在KnapsackManager中注册相应的事件。
Paste_Image.png
分析拖拽事件的核心实现点:
由于拖拽事件,就是控制这个DragItem的显示和隐藏,并不是真正的在UI场景通过鼠标改变格子中的Item的位置。当我们没有拖拽时这个DragItem就隐藏,开始拖拽时这个Item就显示。(拖拽时原来格子中的物品已经被删除了,我们只是在做不停的删除和实例化操作而已)
所以我们需要获取这个DragItem的引用,以及是否开始拖拽的标志位,并在Unity的Inspector面板中进行赋值。
Paste_Image.png
由于我们拖拽的优先级是高于提示框的显示的,我们在拖拽的时候是不应该显示提示框的,所以我们改变层次结构。
Paste_Image.png
接着进行新注册号的两个Drag的回调方法的实现。
GridUI_OnLeftBeginDrag开始拖拽方法:我们在考虑开始拖拽时,我们应该先判断我们当前拖拽的这个格子中是否有物品没有就返回,有的话,就通过ItemModel类拿到它的信息,并使DragItem的样式与之对应。最后按照之后设计好的思想将它删除。
Paste_Image.png
GridUI_OnLeftEndDrag:这个回调方法是重中之重,我们之前也理清了思路,当拖拽结束时无非也就是四种情况,所以根据这四种情况去实现即可。
Paste_Image.png
四种情况的if else架构:
Paste_Image.png
第一种情况:由于之前在Drag开始的时候对象已经删除了但是数据字典中的Item对象仍然存在所以需要在实例化新的之前的这个对象以后把原来的数据删除即可。
Paste_Image.png
第一种情况:由于之前在Drag开始的时候对象已经删除了但是数据字典中的Item对象仍然存在,并且拖拽开始时也没有对拖拽结束到达的格子的物品进行删除,所以我们要先将两个物品删除,并将它们原来的信息得到后删除原来在ItemModel中的数据。并重新实例化两个对象,在实例化的时候交换它们的位置即可。
Paste_Image.png
第三种情况:由于之前在Drag开始的时候对象已经删除了但是数据字典中的Item对象仍然存在,这时对游戏对象进行还原操作即可。
Paste_Image.png
第四种情况:由于之前在Drag开始的时候对象已经删除了,这个删除数据字典中的值即可。
Paste_Image.png
最终演示:
VR开发者,大学英语加软件双学位,一年Unity开发经验,半年VR开发经验及半年创业经验,欢迎交流与分享 个人网站拒绝访问 |
| 百度云加速
请打开cookies.
此网站 () 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3ba4aa-ua98).
重新安装浏览器,或使用别的浏览器UGUI处理ScrollRect的滑动被OnDrag函数拦截的一点技巧 - CSDN博客
UGUI处理ScrollRect的滑动被OnDrag函数拦截的一点技巧
笔程序小白一名,刚接触unity不久,在探索UGUI的过程中遇到了一个问题,
Hierarchy界面和Scrollview的设置如图:
要实现的效果是(1)鼠标上下滑动时,CardList作为一个整体可以随鼠标上下滑动时。
&&&&&&&&&&&&&&&&&&&&&&&&&&&(2)鼠标左右滑动时,Cardunit&元素中的一个值Num_Card可以增减。
由于Cardunit在上面,他会拦截调Scrollview的ONDrag函数,导致不能实现(1)功能,
不知道小伙伴们是怎么处理的,欢迎告诉我更好的方法。
下面说说我的方法,起个抛砖引玉的效果。
&&& 我是在Cardunit上挂了一个脚本重写了下面的3个函数,在函数里直接调用了Scrollview里面被拦截的函数(scrollRect就是Scrollview上挂的ScrollRect组件)
代码如下:
&&& public& void OnBeginDrag(PointerEventData eventData)
&&scrollRect.OnBeginDrag (eventData);
&public void OnDrag(PointerEventData eventData)
&&vec_drap = eventData.
&&&if (Mathf.Abs (vec_drap.x) & value_MinDrog && Mathf.Abs (vec_drap.x) & Mathf.Abs (vec_drap.y)) {
&&&&scrollRect.OnDrag (eventData);
&&&&numCanChange =
&&&} else if (Mathf.Abs (vec_drap.x) & value_MinDrog && Mathf.Abs (vec_drap.x) & Mathf.Abs (vec_drap.y)) {
&&&&numCanChange =
&&//eventData.IsScrolling();
&&Debug.Log (&OnDrag& + eventData.delta);
&public void OnEndDrag(PointerEventData eventData)
&&scrollRect.OnEndDrag (eventData);
&&Debug.Log (eventData.delta);
&&if ( vec_drap.x &=0 && numCanChange) {
&&&if (num & 3)
&&&&num++;
&&&cardNum .text = num + &&;
&&&numCanChange =
&&} else if ( vec_drap.x &=0 && numCanChange) {
&&&if(num&0)
&&&&num--;
&&&cardNum .text& = num+&&;
&&&numCanChange =
&&//scrollRect.OnEndDrag(eventData);
这样基本实现了我要的功能,就是不知道在真正的游戏开发中大牛们是怎么处理的,欢迎批评指正啊。
第一篇博客,有点小激动呢
本文已收录于以下专栏:
相关文章推荐
设置ScrollView的滚动条为隐藏的方法,scrollview滚动条
要实现ScrollView滚动条的隐藏,有两种方法,
一种是在XML的ScrollView布局中加入属性and...
using UnityE
using System.C
using UnityEngine.EventS
using UnityEngine.UI;
using UnityE
using System.Collections.G
using UnityEngine.EventS
using UnityEngi...
今天参考网上的资料写了一个简单的动画,刚开始的时候,确实困难重重:
1、当我们在Activity里面获得View对象的时候,无论是getMeasuredHeight()还是getHehgit()方法...
1、效果图2、思路主要根据Scroll Rect组件的normalizedPosition属性来判断。具体参考/nsky/p/4854002.html 后半...
物品类中继承以下5个接口 
   注:using UnityEngine.EventS
IBeingDragHandler (OnBeingDrag)IDragHand...
1.在button上挂Box Collider,勾上Is Trigger.添加UIButtonMessage,设置Target和FunctionName。
2,.用在GameObject上挂UIE...
using UnityE
using System.C
using UnityEngine.EventS
public class Tool : Mo...
using UnityE
using System.C
using System.Collections.G
public class Test : M...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
UGUI研究院之判断鼠标或者手指是否点击在UI上(六)
UGUI研究院之判断鼠标或者手指是否点击在UI上(六)
围观79611次
编辑日期: 字体:
比如战斗场景,UI和3D场景同时都需要响应触摸事件,如果同时响应可能就会出现触摸UI的时候影响到了3D部分。为了解决这个问题在判断3D响应之前要先判断手指是否点击在UI上。 以前NGUI的时候都是自己来发送射线判断,现在UGUI好了系统提供了更为简便的方法。
123456789101112131415161718192021222324252627282930313233343536373839
#if UNITY_ANDROID && !UNITY_EDITOR#define ANDROID#endif&&#if UNITY_IPHONE && !UNITY_EDITOR#define IPHONE#endif&&&using UnityEngine;using UnityEngine.UI;using System.Collections;using UnityEngine.EventSystems;public class NewBehaviourScript : MonoBehaviour {& // Use this for initialization void Start () {
} & void Update() {
if (Input.GetMouseButtonDown(0)||(Input.touchCount &0 && Input.GetTouch(0).phase == TouchPhase.Began))
{#if IPHONE || ANDROID
if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))#else
if (EventSystem.current.IsPointerOverGameObject())#endif
Debug.Log("当前触摸在UI上");
Debug.Log("当前没有触摸在UI上");
这段代码我在Android上已经测试通过。 哦 我用的是unity5.1
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!说到拖拽,那必然离不开坐标,UGUI 的坐标有点不一样,它有两种坐标,一种是屏幕坐标,还有一种就是 UI
在Canvas内的坐标(暂时叫做ugui坐标),这两个坐标是不一样的,所以拖拽就需要转换。
因为鼠标的移动是屏幕坐标,而 UI
的移动是ugui坐标。转换的方法:
RectTransformUtility.ScreenPointToLocalPointInRectangle ( …
这个方法可以把屏幕坐标转换成 ugui 坐标。这里我们只需要知道 UI 的坐标和鼠标的坐标是不一样的,他们之间的相互移动需要转换就行了。
既然需要转换,就少不了使用方法。所以这里有一些官方的 UGUI监听事件:
要给控件添加以上的监听事件,有三种方法:
1:编写一个类,实现上面的接口(知道用哪个,实现哪个),给空间添加此脚本。
2:添加EventTrigger这个组件。
添加想要添加的监听
然后就像给Buttong添加监听一样添加方法就行。
3:程序动态添加。
这里我使用第一种方法。新建一个 2D项目。场景中添加一张图片(不一定要图片,其他控件也行),然后给图片添加脚本,名为MyDrag,编辑:
using UnityE
using UnityEngine.EventS
using System.C
//给空间添加监听事件要实现的一些接口
public class MyDrag : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler,
IEndDragHandler, IPointerEnterHandler, IPointerExitHandler
public RectT
//得到canvas的ugui坐标
private RectTransform imgR
//得到图片的ugui坐标
Vector2 offset = new Vector3();
//用来得到鼠标和图片的差值
Vector3 imgReduceScale = new Vector3(<span style="color: #.8f, <span style="color: #.8f, <span style="color: #);
//设置图片缩放
Vector3 imgNormalScale = new Vector3(<span style="color: #, <span style="color: #, <span style="color: #);
//正常大小
// Use this for initialization
void Start()
imgRect = GetComponent&RectTransform&();
//当鼠标按下时调用 接口对应
IPointerDownHandler
public void OnPointerDown(PointerEventData eventData)
Vector2 mouseDown = eventData.
//记录鼠标按下时的屏幕坐标
Vector2 mouseUguiPos = new Vector2();
//定义一个接收返回的ugui坐标
//RectTransformUtility.ScreenPointToLocalPointInRectangle():把屏幕坐标转化成ugui坐标
//canvas:坐标要转换到哪一个物体上,这里img父类是Canvas,我们就用Canvas
//eventData.enterEventCamera:这个事件是由哪个摄像机执行的
//out mouseUguiPos:返回转换后的ugui坐标
//isRect:方法返回一个bool值,判断鼠标按下的点是否在要转换的物体上
bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDown, eventData.enterEventCamera, out mouseUguiPos);
if (isRect)
//计算图片中心和鼠标点的差值
offset = imgRect.anchoredPosition - mouseUguiP
//当鼠标拖动时调用
对应接口 IDragHandler
public void OnDrag(PointerEventData eventData)
Vector2 mouseDrag = eventData.
//当鼠标拖动时的屏幕坐标
Vector2 uguiPos = new Vector2();
//用来接收转换后的拖动坐标
//和上面类似
bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDrag, eventData.enterEventCamera, out uguiPos);
if (isRect)
//设置图片的ugui坐标与鼠标的ugui坐标保持不变
imgRect.anchoredPosition = offset + uguiP
//当鼠标抬起时调用
IPointerUpHandler
public void OnPointerUp(PointerEventData eventData)
offset = Vector2.
//当鼠标结束拖动时调用
IEndDragHandler
public void OnEndDrag(PointerEventData eventData)
offset = Vector2.
//当鼠标进入图片时调用
IPointerEnterHandler
public void OnPointerEnter(PointerEventData eventData)
imgRect.localScale = imgReduceS
//缩小图片
//当鼠标退出图片时调用
IPointerExitHandler
public void OnPointerExit(PointerEventData eventData)
imgRect.localScale = imgNormalS
//回复图片
现在就实现了简单的拖放功能。
阅读(...) 评论()

我要回帖

更多关于 h5 拖拽 的文章

 

随机推荐