查看: 30935|回复: 183
收起左侧

[蓬莱仙羽] Unity3d UGUI缩放循环拖动展示卡牌效果

  [复制链接]

[蓬莱仙羽] Unity3d UGUI缩放循环拖动展示卡牌效果  [复制链接]

蓬莱仙羽 发表于 2017-5-8 18:53:26 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  184 浏览:  30935
本帖最后由 guangling 于 2017-5-11 13:38 编辑

需求:游戏中展示卡牌这种效果也是蛮酷炫并且使用的一种常见效果,下面我们就来实现以下这个效果是如何实现。


思考:第一看看到这个效果,我们首先会想到UGUI里面的ScrollRect,当然也可以用ScrollRect来实现缩短ContentSize的width来自动实现重叠效果,然后中间左右的卡牌通过计算来显示缩放,这里我并没有用这种思路来实现,我提供另外一种思路,就是自己去计算当前每个卡牌的位置和缩放值,不用UGUI的内置组件。


CODE:
1.卡牌拖动组件:
[AppleScript] 纯文本查看 复制代码
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public enum DragPosition
{
        Left,
        Right,
        Up,
        Down,
}

[RequireComponent(typeof(Image))]
public class CDragOnCard : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
        public bool dragOnSurfaces = true;
        public ScrollRect m_ScrollRect = null;
        public CFixGridRect m_FixGridRect = null;
        private RectTransform m_DraggingPlane;

        public bool isVertical = false;
        private bool isSelf = false;
        private DragPosition m_dragPosition = DragPosition.Left;

        public System.Action<DragPosition> DragCallBack = null;

        public void OnBeginDrag(PointerEventData eventData)
        {
                Vector2 touchDeltaPosition = Vector2.zero;
#if UNITY_EDITOR
                float delta_x = Input.GetAxis("Mouse X");
                float delta_y = Input.GetAxis("Mouse Y");
                touchDeltaPosition = new Vector2(delta_x, delta_y);

#elif UNITY_ANDROID || UNITY_IPHONE
        touchDeltaPosition = Input.GetTouch(0).deltaPosition;  
#endif
                if (isVertical)
                {
                        if(touchDeltaPosition.y > 0)
                        {
                                UnityEngine.Debug.Log("上拖");
                                m_dragPosition = DragPosition.Up;
                        }
                        else
                        {
                                UnityEngine.Debug.Log("下拖");
                                m_dragPosition = DragPosition.Down;
                        }

                        if (Mathf.Abs(touchDeltaPosition.x) > Mathf.Abs(touchDeltaPosition.y))
                        {
                                isSelf = true;
                                var canvas = FindInParents<Canvas>(gameObject);
                                if (canvas == null)
                                        return;

                                if (dragOnSurfaces)
                                        m_DraggingPlane = transform as RectTransform;
                                else
                                        m_DraggingPlane = canvas.transform as RectTransform;

                        }
                        else
                        {
                                isSelf = false;
                                if (m_ScrollRect != null)
                                        m_ScrollRect.OnBeginDrag(eventData);
                        }
                }
                else //水平
                {
                        if (touchDeltaPosition.x > 0)
                        {
                                UnityEngine.Debug.Log("右移");
                                m_dragPosition = DragPosition.Right;
                        }
                        else
                        {
                                UnityEngine.Debug.Log("左移");
                                m_dragPosition = DragPosition.Left;
                        }

                        if (Mathf.Abs(touchDeltaPosition.x) < Mathf.Abs(touchDeltaPosition.y))
                        {
                                isSelf = true;
                                var canvas = FindInParents<Canvas>(gameObject);
                                if (canvas == null)
                                        return;

                                if (dragOnSurfaces)
                                        m_DraggingPlane = transform as RectTransform;
                                else
                                        m_DraggingPlane = canvas.transform as RectTransform;
                        }
                        else
                        {
                                isSelf = false;
                                if (m_ScrollRect != null)
                                        m_ScrollRect.OnBeginDrag(eventData);
                        }
                }
        }

        public void OnDrag(PointerEventData data)
        {
                if (isSelf)
                {

                }
                else
                {
                        if (m_ScrollRect != null)
                                m_ScrollRect.OnDrag(data);
                }
        }

        public void OnEndDrag(PointerEventData eventData)
        {
                if (isSelf)
                {
                        
                }
                else
                {
                        if (m_ScrollRect != null)
                                m_ScrollRect.OnEndDrag(eventData);
                        if (m_FixGridRect != null)
                                m_FixGridRect.OnEndDrag(eventData);
                }

                if (DragCallBack != null)
                        DragCallBack(m_dragPosition);
        }

        static public T FindInParents<T>(GameObject go) where T : Component
        {
                if (go == null) return null;
                var comp = go.GetComponent<T>();

                if (comp != null)
                        return comp;

                Transform t = go.transform.parent;
                while (t != null && comp == null)
                {
                        comp = t.gameObject.GetComponent<T>();
                        t = t.parent;
                }
                return comp;
        }
}



2.卡牌组件
[AppleScript] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class EnhanceItem : MonoBehaviour
{
        // 在ScrollViewitem中的索引
        // 定位当前的位置和缩放
        public int scrollViewItemIndex = 0;
        public bool inRightArea = false;

        private Vector3 targetPos = Vector3.one;
        private Vector3 targetScale = Vector3.one;

        private Transform mTrs;
        private Image mImage;

        private int index = 1;
        public void Init(int cardIndex = 1)
        {
                index = cardIndex;
                mTrs = this.transform;
                mImage = this.GetComponent<Image>();
                mImage.sprite = Resources.Load<Sprite>(string.Format("Texture/card_bg_big_{0}", cardIndex % 6 + 1));
                this.gameObject.GetComponent<Button>().onClick.AddListener(delegate () { OnClickScrollViewItem(); });
        }

        // 当点击Item,将该item移动到中间位置
        private void OnClickScrollViewItem()
        {
                Debug.LogError("点击" + index);
                EnhancelScrollView.GetInstance().SetHorizontalTargetItemIndex(scrollViewItemIndex);
        }

        /// <summary>
        /// 更新该Item的缩放和位移
        /// </summary>
        public void UpdateScrollViewItems(float xValue, float yValue, float scaleValue)
        {
                targetPos.x = xValue;
                targetPos.y = yValue;
                targetScale.x = targetScale.y = scaleValue;

                mTrs.localPosition = targetPos;
                mTrs.localScale = targetScale;
        }

        public void SetSelectColor(bool isCenter)
        {
                if (mImage == null)
                        mImage = this.GetComponent<Image>();

                if (isCenter)
                        mImage.color = Color.white;
                else
                        mImage.color = Color.gray;
        }
}



3.自定义的ScrollView组件
[AppleScript] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class EnhancelScrollView : MonoBehaviour
{
        public AnimationCurve scaleCurve;
        public AnimationCurve positionCurve;
        public float posCurveFactor = 500.0f;
        public float yPositionValue = 46.0f;

        public List<EnhanceItem> scrollViewItems = new List<EnhanceItem>();
        private List<Image> imageTargets = new List<Image>();

        private EnhanceItem centerItem;
        private EnhanceItem preCenterItem;

        private bool canChangeItem = true;

        public float dFactor = 0.2f;

        private float[] moveHorizontalValues;
        private float[] dHorizontalValues;

        public float horizontalValue = 0.0f;
        public float horizontalTargetValue = 0.1f;

        private float originHorizontalValue = 0.1f;
        public float duration = 0.2f;
        private float currentDuration = 0.0f;

        private static EnhancelScrollView instance;

        private bool isInit = false;
        public static EnhancelScrollView GetInstance()
        {
                return instance;
        }

        void Awake()
        {
                instance = this;
        }

        public void Init()
        {
                if ((scrollViewItems.Count % 2) == 0)
                {
                        Debug.LogError("item count is invaild,please set odd count! just support odd count.");
                }

                if (moveHorizontalValues == null)
                        moveHorizontalValues = new float[scrollViewItems.Count];

                if (dHorizontalValues == null)
                        dHorizontalValues = new float[scrollViewItems.Count];

                if (imageTargets == null)
                        imageTargets = new List<Image>();

                int centerIndex = scrollViewItems.Count / 2;
                for (int i = 0; i < scrollViewItems.Count; i++)
                {
                        scrollViewItems[i].scrollViewItemIndex = i;
                        Image tempImage = scrollViewItems[i].gameObject.GetComponent<Image>();
                        imageTargets.Add(tempImage);

                        dHorizontalValues[i] = dFactor * (centerIndex - i);

                        dHorizontalValues[centerIndex] = 0.0f;
                        moveHorizontalValues[i] = 0.5f - dHorizontalValues[i];
                        scrollViewItems[i].SetSelectColor(false);
                }

                //centerItem = scrollViewItems[centerIndex];
                canChangeItem = true;
                isInit = true;
        }

        public void UpdateEnhanceScrollView(float fValue)
        {
                for (int i = 0; i < scrollViewItems.Count; i++)
                {
                        EnhanceItem itemScript = scrollViewItems[i];
                        float xValue = GetXPosValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
                        float scaleValue = GetScaleValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
                        itemScript.UpdateScrollViewItems(xValue, yPositionValue, scaleValue);
                }
        }

        void Update()
        {
                if (!isInit)
                        return;
                currentDuration += Time.deltaTime;
                SortDepth();
                if (currentDuration > duration)
                {
                        currentDuration = duration;

                        //if (centerItem != null)
                        //{
                        //        centerItem.SetSelectColor(true);
                        //}

                        if (centerItem == null)
                        {
                                var obj = transform.GetChild(transform.childCount - 1);
                                if (obj != null)
                                        centerItem = obj.GetComponent<EnhanceItem>();
                                if (centerItem != null)
                                        centerItem.SetSelectColor(true);
                        }
                        else
                                centerItem.SetSelectColor(true);
                        if (preCenterItem != null)
                                preCenterItem.SetSelectColor(false);
                        canChangeItem = true;
                }

                float percent = currentDuration / duration;
                horizontalValue = Mathf.Lerp(originHorizontalValue, horizontalTargetValue, percent);
                UpdateEnhanceScrollView(horizontalValue);
        }

        private float GetScaleValue(float sliderValue, float added)
        {
                float scaleValue = scaleCurve.Evaluate(sliderValue + added);
                return scaleValue;
        }

        private float GetXPosValue(float sliderValue, float added)
        {
                float evaluateValue = positionCurve.Evaluate(sliderValue + added) * posCurveFactor;
                return evaluateValue;
        }

        public void SortDepth()
        {
                imageTargets.Sort(new CompareDepthMethod());
                for (int i = 0; i < imageTargets.Count; i++)
                        imageTargets[i].transform.SetSiblingIndex(i);
        }

        public class CompareDepthMethod : IComparer<Image>
        {
                public int Compare(Image left, Image right)
                {
                        if (left.transform.localScale.x > right.transform.localScale.x)
                                return 1;
                        else if (left.transform.localScale.x < right.transform.localScale.x)
                                return -1;
                        else
                                return 0;
                }
        }

        private int GetMoveCurveFactorCount(float targetXPos)
        {
                int centerIndex = scrollViewItems.Count / 2;
                for (int i = 0; i < scrollViewItems.Count; i++)
                {
                        float factor = (0.5f - dFactor * (centerIndex - i));

                        float tempPosX = positionCurve.Evaluate(factor) * posCurveFactor;
                        if (Mathf.Abs(targetXPos - tempPosX) < 0.01f)
                                return Mathf.Abs(i - centerIndex);
                }
                return -1;
        }

        public void SetHorizontalTargetItemIndex(int itemIndex)
        {
                if (!canChangeItem)
                        return;

                EnhanceItem item = scrollViewItems[itemIndex];
                if (centerItem == item)
                        return;

                canChangeItem = false;
                preCenterItem = centerItem;
                centerItem = item;

                float centerXValue = positionCurve.Evaluate(0.5f) * posCurveFactor;
                bool isRight = false;
                if (item.transform.localPosition.x > centerXValue)
                        isRight = true;

                int moveIndexCount = GetMoveCurveFactorCount(item.transform.localPosition.x);
                if (moveIndexCount == -1)
                {
                        moveIndexCount = 1;
                }

                float dvalue = 0.0f;
                if (isRight)
                        dvalue = -dFactor * moveIndexCount;
                else
                        dvalue = dFactor * moveIndexCount;

                horizontalTargetValue += dvalue;
                currentDuration = 0.0f;
                originHorizontalValue = horizontalValue;
        }

        public void OnBtnRightClick()
        {
                if (!canChangeItem)
                        return;
                int targetIndex = centerItem.scrollViewItemIndex + 1;
                if (targetIndex > scrollViewItems.Count - 1)
                        targetIndex = 0;
                SetHorizontalTargetItemIndex(targetIndex);
        }

        public void OnBtnLeftClick()
        {
                if (!canChangeItem)
                        return;
                int targetIndex = centerItem.scrollViewItemIndex - 1;
                if (targetIndex < 0)
                        targetIndex = scrollViewItems.Count - 1;
                SetHorizontalTargetItemIndex(targetIndex);
        }
}


Demo下载:
游客,如果您要查看本帖隐藏内容请回复

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

评分

参与人数 2泰斗币 +8 热心值 +1 收起 理由
gzx848383387 + 7 为您的才华点赞
马三小伙儿 + 1 + 1 赞一个!

查看全部评分

+1
31128°C
184
  • 雪漏
  • isygqn1
  • 后羿之弓
  • 瓦片
  • xenost
过: 他们
因分享而快乐,学习以自强!
雪漏 发表于 2017-5-9 09:37:11 显示全部楼层
又是家的吧,好多家的
因分享而快乐,学习以自强!
isygqn1 发表于 2017-5-8 23:03:57 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
因分享而快乐,学习以自强!
后羿之弓 发表于 2017-5-8 23:36:33 显示全部楼层
好东东西收藏一下
因分享而快乐,学习以自强!
瓦片 发表于 2017-5-9 00:48:38 显示全部楼层
谢谢分享,已经收藏了
因分享而快乐,学习以自强!
xenost 发表于 2017-5-9 09:08:35 显示全部楼层
好东西,感谢楼主分享
因分享而快乐,学习以自强!
漂泊的疯 发表于 2017-5-9 09:38:30 显示全部楼层
多谢分享,很不错的效果
因分享而快乐,学习以自强!
jingfengji 发表于 2017-5-9 10:10:15 显示全部楼层
下载看看,这个游戏里挺常见的,多谢分享
因分享而快乐,学习以自强!
jingfengji 发表于 2017-5-9 10:13:36 显示全部楼层
额,链接么?老师
因分享而快乐,学习以自强!
wjhot 发表于 2017-5-9 10:15:57 显示全部楼层
谢谢分享!!!!!
因分享而快乐,学习以自强!
laugher 发表于 2017-5-9 10:42:07 显示全部楼层
感谢分享
因分享而快乐,学习以自强!
simida999 发表于 2017-5-9 15:31:14 显示全部楼层
好厉害呀,膜拜大神呵呵
因分享而快乐,学习以自强!
dkboy00 发表于 2017-5-9 15:31:32 显示全部楼层
谢谢分享
因分享而快乐,学习以自强!
huiyun 发表于 2017-5-9 15:32:31 显示全部楼层
参考参考!!!!!!!!!!!!!!!!!!
因分享而快乐,学习以自强!
黄建泉 发表于 2017-5-9 15:34:13 显示全部楼层
6777777777777777
因分享而快乐,学习以自强!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 沪ICP备14023207号-9 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.4

1
QQ