最近项目中的活动面板要做来回滚动卡牌预览效果,感觉自己来写的话,也能写,但是可能会比较耗时,看到Github上有开源的项目,于是就借用了,Github的资源地址是:https://github.com/tinyantstudio/EnhancedScrollView,感谢作者tinyantstudio的分享。

本篇博客旨在告诉大家如何利用这个插件。

插件的核心在于工程中的6个脚本,以下是六个脚本的源码:

DragEnhanceView.cs

using UnityEngine;
using System.Collections;public class DragEnhanceView : MonoBehaviour
{private EnhanceScrollView enhanceScrollView;public void SetScrollView(EnhanceScrollView view){enhanceScrollView = view;}void OnEnhanceViewDrag(Vector2 delta){if (enhanceScrollView != null)enhanceScrollView.OnDragEnhanceViewMove(delta);}void OnEnhaneViewDragEnd(){if (enhanceScrollView != null)enhanceScrollView.OnDragEnhanceViewEnd();}
}

EnhanceScrollViewDragController.cs

using UnityEngine;
using System.Collections;public class EnhanceScrollViewDragController : MonoBehaviour
{private Vector2 lastPosition = Vector2.zero;private Vector2 cachedPosition = Vector2.zero;private GameObject dragTarget;private Camera targetCamera;private int rayCastMask = 0;private bool dragStart = false;public void SetTargetCameraAndMask(Camera camera, int mask){this.targetCamera = camera;this.rayCastMask = mask;}void Update(){if (this.targetCamera == null)return;
#if UNITY_EDITORProcessMouseInput();
#elif UNITY_IOS || UNITY_ANDROIDProcessTouchInput();
#endif}/// <summary>/// Process Mouse Input/// </summary>private void ProcessMouseInput(){if (Input.GetMouseButtonDown(0)){if (targetCamera == null)return;dragTarget = RayCast(this.targetCamera, Input.mousePosition);lastPosition.x = Input.mousePosition.x;lastPosition.y = Input.mousePosition.y;}if (Input.GetMouseButton(0)){if (dragTarget == null)return;cachedPosition.x = Input.mousePosition.x;cachedPosition.y = Input.mousePosition.y;Vector2 delta = cachedPosition - lastPosition;if (!dragStart && delta.sqrMagnitude != 0f)dragStart = true;if (dragStart){// Notify targetdragTarget.SendMessage("OnEnhanceViewDrag", delta, SendMessageOptions.DontRequireReceiver);}lastPosition = cachedPosition;}if (Input.GetMouseButtonUp(0)){if (dragTarget != null && dragStart){dragTarget.SendMessage("OnEnhaneViewDragEnd", SendMessageOptions.DontRequireReceiver);}dragTarget = null;dragStart = false;}}/// <summary>/// Process Touch input/// </summary>private void ProcessTouchInput(){if (Input.touchCount > 0){Touch touch = Input.GetTouch(0);if (touch.phase == TouchPhase.Began){if (targetCamera == null)return;dragTarget = RayCast(this.targetCamera, Input.mousePosition);}else if (touch.phase == TouchPhase.Moved){if (dragTarget == null)return;if (!dragStart && touch.deltaPosition.sqrMagnitude != 0f){dragStart = true;}if (dragStart){// Notify targetdragTarget.SendMessage("OnEnhanceViewDrag", touch.deltaPosition, SendMessageOptions.DontRequireReceiver);}}else if (touch.phase == TouchPhase.Ended){if (dragTarget != null && dragStart){dragTarget.SendMessage("OnEnhaneViewDragEnd", SendMessageOptions.DontRequireReceiver);}dragTarget = null;dragStart = false;}}}public GameObject RayCast(Camera cam, Vector3 inPos){Vector3 pos = cam.ScreenToViewportPoint(inPos);if (float.IsNaN(pos.x) || float.IsNaN(pos.y))return null;if (pos.x < 0f || pos.x > 1f || pos.y < 0f || pos.y > 1f) return null;Ray ray = cam.ScreenPointToRay(inPos);float dis = 100f;RaycastHit[] hits = Physics.RaycastAll(ray, dis, rayCastMask);if (hits.Length > 0){for (int i = 0; i < hits.Length; i++){GameObject go = hits[i].collider.gameObject;DragEnhanceView dragView = go.GetComponent<DragEnhanceView>();if (dragView == null)continue;else{// just return current hover object our drag targetreturn go;}}}return null;}
}

EnhanceItem.cs

using UnityEngine;
using System.Collections;public class EnhanceItem : MonoBehaviour
{// Start indexprivate int curveOffSetIndex = 0;public int CurveOffSetIndex{get { return this.curveOffSetIndex; }set { this.curveOffSetIndex = value; }}// Runtime real index(Be calculated in runtime)private int curRealIndex = 0;public int RealIndex{get { return this.curRealIndex; }set { this.curRealIndex = value; }}// Curve center offset private float dCurveCenterOffset = 0.0f;public float CenterOffSet{get { return this.dCurveCenterOffset; }set { dCurveCenterOffset = value; }}private Transform mTrs;void Awake(){mTrs = this.transform;OnAwake();}void Start(){OnStart();}// Update Item's status// 1. position// 2. scale// 3. "depth" is 2D or z Position in 3D to set the front and back itempublic void UpdateScrollViewItems(float xValue,float depthCurveValue,int depthFactor,float itemCount,float yValue,float scaleValue){Vector3 targetPos = Vector3.one;Vector3 targetScale = Vector3.one;// positiontargetPos.x = xValue;targetPos.y = yValue;mTrs.localPosition = targetPos;// Set the "depth" of item// targetPos.z = depthValue;SetItemDepth(depthCurveValue, depthFactor, itemCount);// scaletargetScale.x = targetScale.y = scaleValue;mTrs.localScale = targetScale;}protected virtual void OnClickEnhanceItem(){EnhanceScrollView.GetInstance.SetHorizontalTargetItemIndex(this);}protected virtual void OnStart(){}protected virtual void OnAwake(){}protected virtual void SetItemDepth(float depthCurveValue, int depthFactor, float itemCount){}// Set the item center statepublic virtual void SetSelectState(bool isCenter){}
}

EnhanceScrollView.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;public class EnhanceScrollView : MonoBehaviour
{public enum InputSystemType{NGUIAndWorldInput, // use EnhanceScrollViewDragController.cs to get the input(keyboard and touch)UGUIInput,         // use UDragEnhanceView for each item to get drag event}// Input system type(NGUI or 3d world, UGUI)public InputSystemType inputType = InputSystemType.NGUIAndWorldInput;// Control the item's scale curvepublic AnimationCurve scaleCurve;// Control the position curvepublic AnimationCurve positionCurve;// Control the "depth"'s curve(In 3d version just the Z value, in 2D UI you can use the depth(NGUI))// NOTE:// 1. In NGUI set the widget's depth may cause performance problem// 2. If you use 3D UI just set the Item's Z positionpublic AnimationCurve depthCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.5f, 1), new Keyframe(1, 0));// The start center index[Tooltip("The Start center index")]public int startCenterIndex = 0;// Offset width between itempublic float cellWidth = 10f;private float totalHorizontalWidth = 500.0f;// vertical fixed position value public float yFixedPositionValue = 46.0f;// Lerp durationpublic float lerpDuration = 0.2f;private float mCurrentDuration = 0.0f;private int mCenterIndex = 0;public bool enableLerpTween = true;// center and preCentered itemprivate EnhanceItem curCenterItem;private EnhanceItem preCenterItem;// if we can change the target itemprivate bool canChangeItem = true;private float dFactor = 0.2f;// originHorizontalValue Lerp to horizontalTargetValueprivate float originHorizontalValue = 0.1f;public float curHorizontalValue = 0.5f;// "depth" factor (2d widget depth or 3d Z value)private int depthFactor = 5;// Drag enhance scroll view[Tooltip("Camera for drag ray cast")]public Camera sourceCamera;private EnhanceScrollViewDragController dragController;public void EnableDrag(bool isEnabled){if (isEnabled){if (inputType == InputSystemType.NGUIAndWorldInput){if (sourceCamera == null){Debug.LogError("## Source Camera for drag scroll view is null ##");return;}if (dragController == null)dragController = gameObject.AddComponent<EnhanceScrollViewDragController>();dragController.enabled = true;// set the camera and maskdragController.SetTargetCameraAndMask(sourceCamera, (1 << LayerMask.NameToLayer("UI")));}}else{if (dragController != null)dragController.enabled = false;}}// targets enhance item in scroll viewpublic List<EnhanceItem> listEnhanceItems;// sort to get right indexprivate List<EnhanceItem> listSortedItems = new List<EnhanceItem>();private static EnhanceScrollView instance;public static EnhanceScrollView GetInstance{get { return instance; }}void Awake(){instance = this;}void Start(){canChangeItem = true;int count = listEnhanceItems.Count;dFactor = (Mathf.RoundToInt((1f / count) * 10000f)) * 0.0001f;mCenterIndex = count / 2;if (count % 2 == 0)mCenterIndex = count / 2 - 1;int index = 0;for (int i = count - 1; i >= 0; i--){listEnhanceItems[i].CurveOffSetIndex = i;listEnhanceItems[i].CenterOffSet = dFactor * (mCenterIndex - index);listEnhanceItems[i].SetSelectState(false);GameObject obj = listEnhanceItems[i].gameObject;if (inputType == InputSystemType.NGUIAndWorldInput){DragEnhanceView script = obj.GetComponent<DragEnhanceView>();if (script != null)script.SetScrollView(this);}else{UDragEnhanceView script = obj.GetComponent<UDragEnhanceView>();if (script != null)script.SetScrollView(this);}index++;}// set the center item with startCenterIndexif (startCenterIndex < 0 || startCenterIndex >= count){Debug.LogError("## startCenterIndex < 0 || startCenterIndex >= listEnhanceItems.Count  out of index ##");startCenterIndex = mCenterIndex;}// sorted itemslistSortedItems = new List<EnhanceItem>(listEnhanceItems.ToArray());totalHorizontalWidth = cellWidth * count;curCenterItem = listEnhanceItems[startCenterIndex];curHorizontalValue = 0.5f - curCenterItem.CenterOffSet;LerpTweenToTarget(0f, curHorizontalValue, false);// // enable the drag actions// EnableDrag(true);}private void LerpTweenToTarget(float originValue, float targetValue, bool needTween = false){if (!needTween){SortEnhanceItem();originHorizontalValue = targetValue;UpdateEnhanceScrollView(targetValue);this.OnTweenOver();}else{originHorizontalValue = originValue;curHorizontalValue = targetValue;mCurrentDuration = 0.0f;}enableLerpTween = needTween;}public void DisableLerpTween(){this.enableLerpTween = false;}/// /// Update EnhanceItem state with curve fTime value/// public void UpdateEnhanceScrollView(float fValue){for (int i = 0; i < listEnhanceItems.Count; i++){EnhanceItem itemScript = listEnhanceItems[i];float xValue = GetXPosValue(fValue, itemScript.CenterOffSet);float scaleValue = GetScaleValue(fValue, itemScript.CenterOffSet);float depthCurveValue = depthCurve.Evaluate(fValue + itemScript.CenterOffSet);itemScript.UpdateScrollViewItems(xValue, depthCurveValue, depthFactor, listEnhanceItems.Count, yFixedPositionValue, scaleValue);}}void Update(){if (enableLerpTween)TweenViewToTarget();}private void TweenViewToTarget(){mCurrentDuration += Time.deltaTime;if (mCurrentDuration > lerpDuration)mCurrentDuration = lerpDuration;float percent = mCurrentDuration / lerpDuration;float value = Mathf.Lerp(originHorizontalValue, curHorizontalValue, percent);UpdateEnhanceScrollView(value);if (mCurrentDuration >= lerpDuration){canChangeItem = true;enableLerpTween = false;OnTweenOver();}}private void OnTweenOver(){if (preCenterItem != null)preCenterItem.SetSelectState(false);if (curCenterItem != null)curCenterItem.SetSelectState(true);}// Get the evaluate value to set item's scaleprivate float GetScaleValue(float sliderValue, float added){float scaleValue = scaleCurve.Evaluate(sliderValue + added);return scaleValue;}// Get the X value set the Item's positionprivate float GetXPosValue(float sliderValue, float added){float evaluateValue = positionCurve.Evaluate(sliderValue + added) * totalHorizontalWidth;return evaluateValue;}private int GetMoveCurveFactorCount(EnhanceItem preCenterItem, EnhanceItem newCenterItem){SortEnhanceItem();int factorCount = Mathf.Abs(newCenterItem.RealIndex) - Mathf.Abs(preCenterItem.RealIndex);return Mathf.Abs(factorCount);}// sort item with X so we can know how much distance we need to move the timeLine(curve time line)static public int SortPosition(EnhanceItem a, EnhanceItem b) { return a.transform.localPosition.x.CompareTo(b.transform.localPosition.x); }private void SortEnhanceItem(){listSortedItems.Sort(SortPosition);for (int i = listSortedItems.Count - 1; i >= 0; i--)listSortedItems[i].RealIndex = i;}public void SetHorizontalTargetItemIndex(EnhanceItem selectItem){if (!canChangeItem)return;if (curCenterItem == selectItem)return;canChangeItem = false;preCenterItem = curCenterItem;curCenterItem = selectItem;// calculate the direction of movingfloat centerXValue = positionCurve.Evaluate(0.5f) * totalHorizontalWidth;bool isRight = false;if (selectItem.transform.localPosition.x > centerXValue)isRight = true;// calculate the offset * dFactorint moveIndexCount = GetMoveCurveFactorCount(preCenterItem, selectItem);float dvalue = 0.0f;if (isRight){dvalue = -dFactor * moveIndexCount;}else{dvalue = dFactor * moveIndexCount;}float originValue = curHorizontalValue;LerpTweenToTarget(originValue, curHorizontalValue + dvalue, true);}// Click the right button to select the next item.public void OnBtnRightClick(){if (!canChangeItem)return;int targetIndex = curCenterItem.CurveOffSetIndex + 1;if (targetIndex > listEnhanceItems.Count - 1)targetIndex = 0;SetHorizontalTargetItemIndex(listEnhanceItems[targetIndex]);}// Click the left button the select next next item.public void OnBtnLeftClick(){if (!canChangeItem)return;int targetIndex = curCenterItem.CurveOffSetIndex - 1;if (targetIndex < 0)targetIndex = listEnhanceItems.Count - 1;SetHorizontalTargetItemIndex(listEnhanceItems[targetIndex]);}public float factor = 0.001f;// On Drag Movepublic void OnDragEnhanceViewMove(Vector2 delta){// In developingif (Mathf.Abs(delta.x) > 0.0f){curHorizontalValue += delta.x * factor;LerpTweenToTarget(0.0f, curHorizontalValue, false);}}// On Drag Endpublic void OnDragEnhanceViewEnd(){// find closed item to be centeredint closestIndex = 0;float value = (curHorizontalValue - (int)curHorizontalValue);float min = float.MaxValue;float tmp = 0.5f * (curHorizontalValue < 0 ? -1 : 1);for (int i = 0; i < listEnhanceItems.Count; i++){float dis = Mathf.Abs(Mathf.Abs(value) - Mathf.Abs((tmp - listEnhanceItems[i].CenterOffSet)));if (dis < min){closestIndex = i;min = dis;}}originHorizontalValue = curHorizontalValue;float target = ((int)curHorizontalValue + (tmp - listEnhanceItems[closestIndex].CenterOffSet));preCenterItem = curCenterItem;curCenterItem = listEnhanceItems[closestIndex];LerpTweenToTarget(originHorizontalValue, target, true);canChangeItem = false;}
}

NGUIEnhanceItem.cs

using UnityEngine;
using System.Collections;/// <summary>
/// NGUI Enhance item example
/// </summary>
public class NGUIEnhanceItem : EnhanceItem
{private UITexture mTexture;protected override void OnAwake(){this.mTexture = GetComponent<UITexture>();UIEventListener.Get(this.gameObject).onClick = OnClickNGUIItem;}private void OnClickNGUIItem(GameObject obj){this.OnClickEnhanceItem();}// Set the item "depth" 2d or 3dprotected override void SetItemDepth(float depthCurveValue, int depthFactor, float itemCount){if (mTexture.depth != (int)Mathf.Abs(depthCurveValue * depthFactor))mTexture.depth = (int)Mathf.Abs(depthCurveValue * depthFactor);}// Item is centeredpublic override void SetSelectState(bool isCenter){if (mTexture == null)mTexture = this.GetComponent<UITexture>();if (mTexture != null)mTexture.color = isCenter ? Color.white : Color.gray;}protected override void OnClickEnhanceItem(){// item was clickedbase.OnClickEnhanceItem();}
}

UGUIEnhanceItem.cs

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;public class UGUIEnhanceItem : EnhanceItem
{private Button uButton;private Image image;protected override void OnStart(){image = GetComponent<Image>();uButton = GetComponent<Button>();uButton.onClick.AddListener(OnClickUGUIButton);}private void OnClickUGUIButton(){OnClickEnhanceItem();}// Set the item "depth" 2d or 3dprotected override void SetItemDepth(float depthCurveValue, int depthFactor, float itemCount){int newDepth = (int)(depthCurveValue * itemCount);this.transform.SetSiblingIndex(newDepth);}public override void SetSelectState(bool isCenter){if (image == null)image = GetComponent<Image>();image.color = isCenter ? Color.white : Color.gray;}
}

导入以上6个脚本以后,我们开始制作效果,先从NGUI开始,我们先在场景中,随便添加一个背景,然后,我们在UIRoot下面添加一个空物体,取名Scrollview,添加EnhanceScrollView.cs脚本,然后制作六个Texture作为Scrollview的子物体,添加DragEnhanceView.cs脚本,NGUIEnhanceItem.cs脚本,BoxCollider组件。接着,我们在六个图片下方添加两个Button,作为左右切换卡牌的按钮,在点击事件中,拖入Scrollview,分别添加OnBtnLeftClick,OnBtnRightClick方法。做完以上操作以后,场景大概是这样:

接着,我们选中Scrollview,调整脚本参数:

ScaleCurve图像参数,设置为如下,左右循环都为pingpong:

PositionCurve图像参数如下,左右循环都为loop:

DepthCurve图像参数如下,左右循环都为loop:

然后把Scrollview的子物体都拖到ListEnhanceItems这个公开数组下:

这样,我们就把配置工作都做好了,运行游戏:

可以看到,效果还不错,左右滑动或者点击切换按钮,就能实现切换卡牌的功能。

接着,我们看一下UGUI的实现,UGUI的UI布局基本和NGUI保持一致,所不同的是Scrollview的子物体添加的脚本不一样,所需要的脚本及组件如下图所示:

然后,还有需要注意的一点是,在Scrollview上的参数配置上,我们需要把InputType这个属性调整为UGUI Input

曲线设置和子物体数组设置和NGUI一样,这里就不再重复了,配置完这些操作以后,运行,UGUI也能实现一样的卡牌滚动效果:

以上,感谢Github。

Unity中游戏卡牌滚动效果,EnhanceScrollview(适用于NGUI,UGUI)相关推荐

  1. 【游戏客户端】实现卡牌翻转效果

    [游戏客户端]实现卡牌翻转效果       之前的博客中,我和大家分享了如何做: 商业化的充值活动 :[商业化充值活动博客] 抽卡系统:[抽奖,抽卡系统博客] 装备系统:[装备系统博客] 红点系统:[ ...

  2. Python批量爬取游戏卡牌信息

    文章目录 前言 一.需求 二.分析 三.处理 四.运行结果 前言 本系列文章来源于真实的需求 本系列文章你来提我来做 本系列文章仅供学习参考 阅读人群:有Python基础.Scrapy框架基础 一.需 ...

  3. Unity中游戏存档方式

    ##游戏存档 ####在Unity中游戏存档有如下四种方式: PlayerPrefs c#序列化 XML序列化 Json **原文链接:**http://blog.csdn.net/a23765363 ...

  4. Unity3D_(游戏)卡牌03_选关界面

      启动屏界面.主菜单界面.选关界面.游戏界面 卡牌01_启动屏界面 传送门 卡牌02_主菜单界面 传送门 卡牌03_选关界面 传送门 卡牌04_游戏界面    传送门 选关界面效果 (鼠标放在不同关 ...

  5. 游戏卡牌半小时拍出8700万天价,法院紧急叫停!

    6月21日,一张<游戏王>的纪念卡牌"青眼白龙"司法拍卖于阿里拍卖上正式开始.然而,距拍卖开始仅半个小时,这张卡牌便.拍出了约8732.61万元的"天价&qu ...

  6. Unity中多张图片形成百叶窗效果(亲测有效)

    首先在Unity中准备好8张图片,也可以其他数量的图片,最好的是这几张图片都是从一张图片分割下来的,能确保这几张图片重新拼回原来的图片.首先在场景中新建一个名WindowShades的C#脚本,并把该 ...

  7. unity中游戏对象的运动控制方法总结

    1.使用unity中的Standard Assets包中的控制器 这个资源在资源商店中搜Standard Assets就可以下载并导入,在其Characters文件夹中有第一人称和第三人称的控制器,在 ...

  8. cocos2dx卡牌翻转效果

    刚学cocos2dx,想要实现卡牌翻转的效果,如下: google之后知道是使用CCOrbitCamera. 使用这条语句(CCOrbitCamera *camera1=CCOrbitCamera:: ...

  9. 【Unity Shader】Unity中利用GrabPass实现玻璃效果

    <入门精要>中模拟玻璃是用了Unity里的一个特殊的Pass来实现的,这个Pass就是GrabPass,比起上一篇博客实现镜子的方法,这个方法我认为相对复杂,因此在实现之前需要对GrabP ...

最新文章

  1. react 统一字段验证_如何使用React的受控输入进行即时表单字段验证
  2. c++ 函数指针_开发经验分享(5) 修改Makefile实现C/C++混合编程
  3. 预言丨AI之后无AI
  4. python实现完全数
  5. 监控服务器怎么增加碟机,微服务业务监控方法及服务器专利_专利申请于2017-12-15_专利查询 - 天眼查...
  6. Codeforces Round #626 (Div. 2) D. Present 按位贡献 + 快排新姿势
  7. 论ACM ICPC_Ruins He
  8. 【VS开发】CTimeSpan类
  9. 《南溪的目标检测学习笔记》——主干网络backbone设计的学习笔记
  10. 一个教务系统多少钱_ERP系统多少钱
  11. dreamweaver序列号免费_dreamweaver8【dreamweaver8序列号】dreamweaver8注册码序列号简体中文版...
  12. 基于STM32的超声波避障小车
  13. 《计算机视觉黑魔法16个实战项目》之扫描全能王
  14. java实验三正式报告
  15. win10中 微软 输入法 简体字 与 繁体字 设定 切换
  16. Adv-Makeup:一种新颖不易察觉且可迁移的人脸识别攻击方法
  17. Linux搭建vpn服务器
  18. 若依(RuoYi-Vue)+Flowable工作流前后端整合教程
  19. 如何使用 JavaScript 制作待办事项列表
  20. C/C++中的exit()函数

热门文章

  1. 一台电脑一天用多少度电
  2. python中uppercase是什么意思_Python string.uppercase方法代码示例
  3. 【思维导图】Java基础笔记整理
  4. 使用pip安装离线包
  5. 两线怎么接三线插座图_三根电线怎么接两根电线图解
  6. 备忘录软件开源_介绍适用于开源软件替代方案的备忘单
  7. Python实现对相同数据分箱小技巧
  8. RecycleView列表中下拉刷新图片错乱的问题
  9. 计算机屏幕暗度怎么调,怎么调电脑屏幕暗度怎么调电脑屏幕暗度<br – 手机爱问...
  10. [算法系列] 搞懂递归, 看这篇就够了 !! 递归设计思路 + 经典例题层层递进