NGUI学习笔记(五): 背包拖拽效果
来源:互联网 发布:ps cs6 for mac破解版 编辑:程序博客网 时间:2024/06/08 06:11
关于拖拽以及交换物品,NGUI有很贴心的UIDragDropItem以及UIContainer两个内置脚本.基本功能已经实现,使用者需要做的就是根据自己的需求Override相应的虚函数.
先展示一下今天要实现的目标效果:
文字说明:
1.我希望被交换的物品在改变自己的位置时,有一段朝目标格子移动的位移动画,而不是很死板的瞬间改变position.
2.如图中所示,当前物品拖拽到了哪个格子上,则对应的格子会有相应的图形状态变化来提示用户.
场景截图:
下面上脚本:
using UnityEngine;using System.Collections;using System.Collections.Generic;public class ExchangableItem : UIDragDropItem { /// <summary> /// 当前拖拽悬停在的那个Container; /// </summary> Transform dragOverContainer; protected override void Start () { base.Start (); } protected override void OnDragStart () { base.OnDragStart (); //每次开始拖拽时都将正在悬停的容器格子置为自身父物体,保证有一个正确的初始值 dragOverContainer = transform.parent; } protected override void OnPress (bool isPressed) { base.OnPress (isPressed); //当对某个Item按下时则其UIWidget(包括所有子物体)的深度都+2,为什么不是+1呢?因为被交换的Item会采用+1,这里要比被交换Item的深度高1. //反之当按压结束时还原深度 List<UIWidget> widgets = new List<UIWidget>(transform.GetComponentsInChildren<UIWidget>()); if (isPressed) { transform.GetComponent<UIWidget> ().depth+=2; foreach (UIWidget widget in widgets) { widget.depth+=2; } } else { transform.GetComponent<UIWidget> ().depth-=2; foreach (UIWidget widget in widgets) { widget.depth-=2; } } } protected override void OnDragDropMove (Vector2 delta) { base.OnDragDropMove (delta); Ray ray = UICamera.mainCamera.ScreenPointToRay (Input.mousePosition); RaycastHit hit; //当拖拽时,用射线检测Layer为Container的Collider,以此来获得被拖拽物在哪个容器的上方. if (Physics.Raycast (ray, out hit, Mathf.Infinity, (1 << LayerMask.NameToLayer ("Container")))) { if (hit.collider.transform != dragOverContainer) { UIPlayTween playTw = dragOverContainer.gameObject.GetComponent<UIPlayTween> (); playTw.resetOnPlay = true; //这里要吐槽一下NGUI内置的Tween功能,我本来想让处于拖拽物下方的容器做循环的颜色变换动画, //但是发现这样根本没法用UIPlayTween将其停止, //这也算是UIPlayTween的一大缺陷, //相比于DoTween简直弱爆了! //这里的反向播放是为了还原到原有状态. playTw.Play (false); print (dragOverContainer.name); dragOverContainer = hit.collider.transform; print (dragOverContainer.name); playTw = dragOverContainer.gameObject.GetComponent<UIPlayTween> (); playTw.resetOnPlay = true; playTw.Play (true); } } } protected override void OnDragEnd () { base.OnDragEnd (); //拖拽结束时也要动画进行反向播放来达到还原状态的目的 UIPlayTween playTw = dragOverContainer.gameObject.GetComponent<UIPlayTween> (); playTw.resetOnPlay = true; playTw.Play (false); } protected override void OnDragDropRelease (GameObject surface) { if (!cloneOnDrag) { // Re-enable the collider if (mButton != null) mButton.isEnabled = true; else if (mCollider != null) mCollider.enabled = true; else if (mCollider2D != null) mCollider2D.enabled = true; // Is there a droppable container? UIDragDropContainer container = surface ? NGUITools.FindInParents<UIDragDropContainer>(surface) : null; if (container != null) { //当这个容器是自身所在容器时直接还原 if (container.transform == mParent) { transform.localPosition = Vector3.zero; mParent.localScale = Vector3.one; return; } // Container found -- parent this object to the container Transform containerTrans = (container.reparentTarget != null) ? container.reparentTarget : container.transform; if (containerTrans.childCount > 0) { Transform parent = mParent; Transform child = containerTrans.GetChild (0); List<UIWidget> widgets = new List<UIWidget>(child.GetComponentsInChildren<UIWidget>()); child.GetComponent<UIWidget> ().depth++; foreach (UIWidget widget in widgets) { widget.depth++; } TweenPosition twpos = child.gameObject.AddComponent<TweenPosition> (); //将mParent中心点坐标转换为世界坐标,其实可以直接用mParent的世界坐标 Vector3 worldPos = mParent.TransformPoint (Vector3.zero); //将mParent的世界坐标转换到child的本地坐标系中 Vector3 localPos = child.InverseTransformPoint (worldPos); //TweenPosition动画是对物体的本地坐标进行改变,这一点很重要,很重要,很重要!!! twpos.to.Set (localPos.x, localPos.y, localPos.z); twpos.duration = 0.2f; //这里要再次吐槽NGUI自带的Tween,连在代码内指定一个动画曲线都这么困难!还要自己指定关键帧 //DoTween里直接封装好了非常多且使用的动画曲线,你需要通过枚举类型指定就可以了 //twpos.animationCurve = new AnimationCurve(new Keyframe[]()); twpos.Play (); twpos.AddOnFinished ( //新建一个代理 new EventDelegate ( //Lambada表达式申明匿名函数 () => { child.GetComponent<UIWidget> ().depth--; foreach (UIWidget widget in widgets) { widget.depth--; } //当动画播放完毕时改变父物体为拖拽物之前的父物体 //注意一定提前记录被拽物之前的父物体,因为这里相当于协同程序结束时的回调 child.parent = parent; child.localPosition = Vector3.zero; child.localScale = Vector3.one; } ) ); mTrans.parent = containerTrans; mTrans.localPosition = Vector3.zero; mTrans.localScale = Vector3.one; } } else { // No valid container under the mouse -- revert the item's parent mTrans.parent = mParent; mTrans.localPosition = Vector3.zero; mTrans.localScale = Vector3.one; } // Update the grid and table references mParent = mTrans.parent; mGrid = NGUITools.FindInParents<UIGrid>(mParent); mTable = NGUITools.FindInParents<UITable>(mParent); // Re-enable the drag scroll view script if (mDragScrollView != null) StartCoroutine(EnableDragScrollView()); // Notify the widgets that the parent has changed NGUITools.MarkParentAsChanged(gameObject); if (mTable != null) mTable.repositionNow = true; if (mGrid != null) mGrid.repositionNow = true; // We're now done OnDragDropEnd(); } else NGUITools.Destroy(gameObject); }}
最后我要补充一下当我做射线检测时,发现只要运行我原本设置好的Layer就会自动发生改变,这是为什么?
经过几次尝试终于发现了原因:
英文的Log信息已经给出了答案,这小细节还挺麻烦的,哈!
阅读全文
0 0
- NGUI学习笔记(五): 背包拖拽效果
- NGUI实现背包效果
- NGUI学习笔记(五)Tweens
- NGUI 背包系统的拖拽
- NGUI 背包系统的拖拽
- NGUI学习笔记(七):UIPanel剪裁粒子效果
- NGUI学习笔记(八):图片(UISprite)灰化效果
- unity ngui学习(五)
- Flex学习笔记(五) 动画效果
- NGUI学习笔记
- 2.NGUI学习笔记
- NGUI学习笔记
- NGUI学习笔记(摘)
- NGUI学习笔记(摘)
- NGUI学习笔记--用法
- NGUI学习笔记
- NGUI学习笔记汇总
- NGUI 学习笔记
- NGUI学习笔记(四):扩展插件HUD与富文本
- 杨辉三角
- Mondriaan's Dream POJ
- java中接口回调的理解
- Xilinx SDK 中 的 'No rule to make target ' / '没有规则可以创建...'
- NGUI学习笔记(五): 背包拖拽效果
- 10067---java集合框架【3】 java1.5新特性 ConcurrentHashMap、Collections.synchronizedMap、Hashtable讨论
- C++笔记之【Webservice通讯中文乱码】的那些事
- 使用gradle创建多项目
- 三种建模方式探索
- 开源OCR引擎Tesseract-OCR
- 数据库系统之三级结构模式
- The First
- 华为——进制转换