
最近想研究UGUI,所以只要涉及UI部分的全都想用UGUI来搞,包括之前写的回合制的一个小实例demo。但是在我研究背包所需功能的时候遇到了瓶颈,让我很是受伤。
像是一个简单的背包,用来存储物品对象就OK了,但是那完全满足不了要求,至少像是拖拽、交换、拖入、切换栏目以及再加点炫酷特效啥的这些都要用吧!
拖拽啥的很简单,一会搞定,但是当做到射线检测的时候直接卡住了,怎么试都不没用,然后就各种查资料,找原因,包括问一些朋友。有的说能实现、有的说实现不了,但是都没有根本性解决我的问题,后来一大神朋友说,unity的UI的事件触发机制有问题,需要改一下射线触发机制,让对象主动触发事件,自己继承一下它的射线检测,如果有3D的对象,还要再自己写触发3D的,听了一下,我倒是明白了,因为我在查资料的过程中也看到这样的字眼出现,不过这要是写就不是一会的事了,我还得先研究一下这个机制,因为之前就不熟悉,要是再遇到问题,又得耗时间。
好在,一位热心朋友的一句代码提醒了我,虽然没解决我的问题,但是却让我想到了解决的办法!下面我就把方法分享给大家:
1、拖拽以及点击效果(比较简单):
创建两个Image,命名为Item,像是背景图片啥的,你们自己放吧,创建一个脚本,随便命名,比如DragItem.cs
加上两个引用,如下:
usingUnityEngine.UI;
usingUnityEngine.EventSystems;
类继承一下IDragHandler,IPointerDownHandler,IPointerUpHandler
然后在代码里写三个方法,如下:
publicvoid OnDrag(PointerEventData eventData){
GetComponent<RectTransform> ().pivot.Set (0, 0);
transform.position = Input.mousePosition;
}
publicvoid OnPointerDown(PointerEventData eventData){
transform.localScale = newVector3 (0.7f, 0.7f, 0.7f);
}
publicvoid OnPointerUp(PointerEventData eventData){
transform.localScale = newVector3 (1f, 1f, 1f);
}
把代码拖到两个Item上,运行程序试一下,可以看到效果

2、射线检测后面物体让其成为父物体
看起来简单的要命,但是却坑了我三天,射线检测机制需要自己来继承,于是我用了一个小方法,来跳过这个,等有空再用那个2D射线来搞吧
首先创建两个panel,一个命名为InitPanel,放到UI的最上面的位置,另一个就Panel不变了吧,放到最下面的位置。
在Panel上创建一个空对象取名grid,然后给其添加一个grid layout group,如下图:

这个组件是用来自动排序的。
代码部分,稍作修改:
//如果对象比较少可以定义一下,然后在面板中指定一下,这样节省遍历次数
[SerializeField] GameObject grid = null;
[SerializeField] GameObject initCanvas = null;
在OnPointerUp 方法中加上这些:
<span style="white-space:pre"> </span>if(eventData.pointerCurrentRaycast.gameObject != null) {
if(eventData.pointerCurrentRaycast.gameObject.name == grid.name) {
transform.SetParent (grid.transform);
}
}
在OnPointerDown 中加上一句:
transform.SetParent (initCanvas.transform, true);
然后在面板中指定一下,如图:

好了,最终效GIF动态图

代码改动了好多,我重新弄了个简单的贴出来给大家看看吧,加了 CanvasGroup,控制射线穿透, 还有那个PanelInit放到最下面去,还是深度和规划的问题,看起来不乱
注意一点就是如果没有CanvasGroup组件的话就添加一个
<span style="white-space:pre"> </span>publicvoid OnDrag(PointerEventData eventData){
GetComponent<RectTransform> ().pivot.Set (0, 0);
transform.position = Input.mousePosition;
}
publicvoid OnPointerDown(PointerEventData eventData){
transform.localScale = newVector3 (0.7f, 0.7f, 0.7f);
transform.SetParent (initCanvas.transform, true);
transform.GetComponent<CanvasGroup> ().blocksRaycasts = false;
}
publicvoid OnPointerUp(PointerEventData eventData){
transform.localScale = newVector3 (1f, 1f, 1f);
if(eventData.pointerCurrentRaycast.gameObject != null) {
if(eventData.pointerCurrentRaycast.gameObject.name == grid.name) {
transform.SetParent (grid.transform);
}
}
transform.GetComponent<CanvasGroup> ().blocksRaycasts = true;
}