物品拖拽[u3d_rpg游戏开发之物品管理(五)]
来源:互联网 发布:淘宝开学季什么时候 编辑:程序博客网 时间:2024/05/05 08:42
之前在网上找了好多方法,总是不适合自己,要么就是不能用之类的,我用的是2017的版本,在这里"全面"解析一下.首先创建一个脚本InventoryItem挂在需要拖拽的Image上,这里的Image是另一个Image的子物体,因为子的Imget我用来显示物品的相应物品的图片,而父的Image我用来显示格子的图片,这样就有了格子里面的物品,可以用来拖动,而且,格子的标签我设为"InventoryItemGird",拖拽结束时就可以通过标签判断是不是格子.
1. 继承接口
u3d的ugui有相应的接口来方便我们实现拖拽功能,除了本来就需要继承的MonoBehaviour外,我们写的脚本再继承三个接口,还得先导入头文件 UnityEngine.EventSystems;
using UnityEngine.EventSystems;public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{}
2. 实现抽象方法
抽象方法同样是三个
using UnityEngine.EventSystems;public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{ /// <summary> /// 实现接口的OnBeginDrag方法,处理开始拖拽时要做的事情 /// </summary> /// <param name="eventData"></param> public void OnBeginDrag(PointerEventData eventData) { } /// <summary> /// 实现接口的OnDrag方法,处理拖动中要做的事情 /// </summary> /// <param name="eventData"></param> public void OnDrag(PointerEventData eventData) { } /// <summary> /// 实现接口的OnEndDrag方法,处理结束时的方法 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { }}
3. 去遮挡
拖拽的时候我们会遇到一个问题,就是拖拽物品的父物体是是一个格子,而格子又位于不同的层,如图:
我把格子取名为Inventory-Item-gird-00至Inventory-Item-gird-34共20个格子,这里的第一个格子Inventory-Item-gird-00在其他格子的后面,ui物体越靠下就越显示在摄像机的越靠外层,所以,当Inventory-Item-gird-00下的物品拖拽到Inventory-Item-gird-34格子的位置时,会被其遮挡我们这里就在最下面再创建一个隐形而不能用画布:Canvas,当我们需要拖动物品时就将该物品的父物体设置为Canvas,拖拽物品就会位于最外层,不会被任何ui遮挡,需要注意的是,当拖拽结束我们需要将父物体设置回来,不然会导致原来格子下的Image没了.
private Transform imageParent;//拖拽物品的父物体 private Canvas imageFather;//获取最外层的画布 private Vector2 drugingRectTransform;//正在被拖拽的图片的原始位置 public void OnBeginDrag(PointerEventData eventData) { imageFather = GameObject.Find("Canvas").GetComponent<Canvas>();//获取在最外层的格子 drugingRectTransform = myImage.rectTransform.position;//获取初始位置 imageParent = transform.parent;//获取父物体的transform transform.SetParent(imageFather.transform);//将物品放在最外层 } /// <summary> /// 将一个物体放在另一个物体下 /// </summary> /// <param name="child">作为子物体</param> /// <param name="parent">作为父物体</param> private void SetParentAndPosition(Transform child, Transform parent)//将child放到parent下作为子物体 { child.SetParent(parent); child.position = parent.position; }
4. 实现穿透
当我们拖拽结束的时候,我们需要判断鼠标停留的位置是否是一个格子,如果是格子才有可能吧物品放进去,如果不是就要让物品还原位置.那么问题来了,拖拽物品始终在鼠标位置,也就是说判断鼠标停留位置的时候,射线判断到的永远是我们正在拖拽的物品.所以我们我让我们在拖拽中的物品不被鼠标射线检测到,也就是使物品实现穿透.这个时候我们的物品位于Canvas下,所以我们只需要让Canvas实现穿透就行了,先给其添加一个组件:Canvas Group
这个组件下的Blocks Raycasts选项就表示所在物体是否会遮挡鼠标射线,这时我们就可以通过代码来控制其开关了.
/// <summary> /// 实现接口的OnBeginDrag方法,处理开始拖拽时要做的事情 /// </summary> /// <param name="eventData"></param> public void OnBeginDrag(PointerEventData eventData) { imageFather = GameObject.Find("Canvas").GetComponent<Canvas>();//获取在最外层的画布 drugingRectTransform = myImage.rectTransform.position;//获取初始位置 imageParent = transform.parent;//获取父物体的transform transform.SetParent(imageFather.transform);//将物品放在最外层 GameObject.Find("Canvas").GetComponent<CanvasGroup>().blocksRaycasts = false;//射线可以穿透物体 }
至此开始拖拽物品的方法完全实现
5. 物品置入
物品置入前还有一个拖拽方法需要实现:
/// <summary> /// 实现接口的OnDrag方法,处理拖动中要做的事情 /// </summary> /// <param name="eventData"></param> public void OnDrag(PointerEventData eventData) { this.GetComponent<RectTransform>().position=Input.mousePosition;//鼠标左键按住拖拽的时候,物体跟着鼠标移动 }
最后就是拖拽结束的方法了.最后一个交换物品的方法可以不用管,我写给自己看的,所有的思路已经很清晰了.
/// <summary> /// 实现接口的OnEndDrag方法,处理结束时的方法 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { SetParentAndPosition(transform, imageParent);//复原父物体 transform.position = drugingRectTransform;//原图归位 ExchangeOfGoods(eventData);//交换物品 GameObject.Find("Canvas").GetComponent<CanvasGroup>().blocksRaycasts = false;//ui事件穿透:置为不能穿透 } /// <summary> /// 格子内的物品进行交换 /// </summary> /// <param name="eventData">参数PointerEventData用于获取鼠标终点位置</param> private void ExchangeOfGoods(PointerEventData eventData) { GameObject go = eventData.pointerCurrentRaycast.gameObject;//获取鼠标下的物体 //如果物体不为空且该物体为物品格子 if (go != null && go.tag.Equals("InventoryItemGird")) { InventoryItemGrid fatherOfThis = this.GetComponentInParent<InventoryItemGrid>();//获取起点格子的脚本 InventoryItemGrid fatherOfThat = go.GetComponent<InventoryItemGrid>();//获取终点格子的脚本 //如果格子为空格子 if (fatherOfThat.id == 0) { fatherOfThat.SetId(fatherOfThis.id,fatherOfThis.num);//向终点格子储存物品 fatherOfThis.ClearInfo();//清空原来格子信息 } else//两格子交换物品 { InventoryItemGrid temp = fatherOfThat;//临时储存终点格子的脚本 fatherOfThat.SetId(fatherOfThis.id, fatherOfThis.num);//向终点格子储存物品 fatherOfThis.SetId(temp.id, temp.num);//向起点格子储存物品 } } }
阅读全文
0 0
- 物品拖拽[u3d_rpg游戏开发之物品管理(五)]
- u3d_rpg游戏开发之物品管理(一)
- u3d_rpg游戏开发之物品管理(二)
- u3d_rpg游戏开发之物品管理(三)
- xml在u3d的使用[u3d_rpg游戏开发之物品管理(四)]
- 游戏开发学习笔记(六)物品信息的管理及读取
- unity 鼠标拖拽物品
- NGUI的物品拖拽
- 物品管理类ItemController
- [Unity3D]Unity3D游戏开发之鼠标旋转、缩放实现3D物品展示
- [Unity3D]Unity3D游戏开发之鼠标旋转、缩放实现3D物品展示
- Unity3D游戏开发之鼠标旋转、缩放实现3D物品展示
- [Unity3D]Unity3D游戏开发之鼠标旋转、缩放实现3D物品展示
- 游戏开发学习笔记(十)购买物品
- RPG游戏黑暗之光Part4:物品模块
- unityUGUI拖拽物品的实现方法
- 人员物品门禁管理方案
- [lua游戏]每10个物品一组发送物品
- redis-安装和简单配置
- 生活小记74
- first time
- 在ubuntu环境下MPI分布式集群搭建(1)
- ros中消息类型的创建
- 物品拖拽[u3d_rpg游戏开发之物品管理(五)]
- 4、基本的线程同步
- github仓库更新代码指令笔记
- Python学习之matplotlib的安装
- 关于虚函数的面试题
- 5、守护线程
- 原木加工
- linux-war文件操作
- 6、ThreadLocal线程变量