unity实现卡牌翻动效果

事实上这是项目需要,我改的一个代码,实际上就是利用unity的一些基础属性实现其效果。啥也不多说了,先上原代码:

/// Credit Mrs. YakaYocha 
/// Sourced from - https://www.youtube.com/channel/UCHp8LZ_0-iCvl-5pjHATsgw
/// Please donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RJ8D9FRFQF9VS

using UnityEngine.Events;

namespace UnityEngine.UI.Extensions
{
    [RequireComponent(typeof(ScrollRect))]
    [AddComponentMenu("Layout/Extensions/Vertical Scroller")]
    public class UIVerticalScroller : MonoBehaviour
    {
        [Tooltip("Scrollable area (content of desired ScrollRect)")]
        public RectTransform _scrollingPanel;
        [Tooltip("Elements to populate inside the scroller")]
        public GameObject[] _arrayOfElements;
        [Tooltip("Center display area (position of zoomed content)")]
        public RectTransform _center;
        [Tooltip("Select the item to be in center on start. (optional)")]
        public int StartingIndex = -1;
        [Tooltip("Button to go to the next page. (optional)")]
        public GameObject ScrollUpButton;
        [Tooltip("Button to go to the previous page. (optional)")]
        public GameObject ScrollDownButton;
        [Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
        public UnityEvent<int> ButtonClicked;


        private float[] distReposition;
        private float[] distance;
        //private int elementsDistance;
        private int minElementsNum;
        private int elementLength;
        //private int elementHalfLength;
        private float deltaY;
        private string result;

        public UIVerticalScroller() { }

        public UIVerticalScroller(RectTransform scrollingPanel, GameObject[] arrayOfElements, RectTransform center)
        {
            _scrollingPanel = scrollingPanel;
            _arrayOfElements = arrayOfElements;
            _center = center;
        }


        public void Awake()
        {
            var scrollRect = GetComponent<ScrollRect>();
            if (!_scrollingPanel)
            {
                _scrollingPanel = scrollRect.content;
            }
            if (!_center)
            {
                Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
            }
            if (_arrayOfElements == null || _arrayOfElements.Length == 0)
            {
                var childCount = scrollRect.content.childCount;
                if (childCount > 0)
                {
                    _arrayOfElements = new GameObject[childCount];
                    for (int i = 0; i < childCount; i++)
                    {
                        _arrayOfElements[i] = scrollRect.content.GetChild(i).gameObject;
                    }                    
                }
            }
        }

        public void Start()
        {
            if (_arrayOfElements.Length < 1)
            {
                Debug.Log("No child content found, exiting..");
                return;
            }

            elementLength = _arrayOfElements.Length;
            distance = new float[elementLength];
            distReposition = new float[elementLength];

            //get distance between buttons
            //elementsDistance = (int)Mathf.Abs(_arrayOfElements[1].GetComponent<RectTransform>().anchoredPosition.y - _arrayOfElements[0].GetComponent<RectTransform>().anchoredPosition.y);
            deltaY = _arrayOfElements[0].GetComponent<RectTransform>().rect.height * elementLength / 3 * 2;
            Vector2 startPosition = new Vector2(_scrollingPanel.anchoredPosition.x, -deltaY);
            _scrollingPanel.anchoredPosition = startPosition;

            for (var i = 0; i < _arrayOfElements.Length; i++)
            {
                AddListener(_arrayOfElements[i], i);
            }

            if (ScrollUpButton)
                ScrollUpButton.GetComponent<Button>().onClick.AddListener(() => { ScrollUp(); });

            if (ScrollDownButton)
                ScrollDownButton.GetComponent<Button>().onClick.AddListener(() => { ScrollDown(); });

            if (StartingIndex > -1)
            {
                StartingIndex = StartingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : StartingIndex;
                SnapToElement(StartingIndex);
            }
        }

        private void AddListener(GameObject button, int index)
        {
            button.GetComponent<Button>().onClick.AddListener(() => DoSomething(index));
        }

        private void DoSomething(int index)
        {
            if (ButtonClicked != null)
            {
                ButtonClicked.Invoke(index);
            }
        }

        public void Update()
        {
            if (_arrayOfElements.Length < 1)
            {
                return;
            }

            for (var i = 0; i < elementLength; i++)
            {
                distReposition[i] = _center.GetComponent<RectTransform>().position.y - _arrayOfElements[i].GetComponent<RectTransform>().position.y;
                distance[i] = Mathf.Abs(distReposition[i]);

                //Magnifying effect
                float scale = Mathf.Max(0.7f, 1 / (1 + distance[i] / 200));
                _arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale, scale, 1f);
            }
            float minDistance = Mathf.Min(distance);

            for (var i = 0; i < elementLength; i++)
            {
                _arrayOfElements[i].GetComponent<CanvasGroup>().interactable = false;
                if (minDistance == distance[i])
                {
                    minElementsNum = i;
                    _arrayOfElements[i].GetComponent<CanvasGroup>().interactable = true;
                    result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
                }
            }

            ScrollingElements(-_arrayOfElements[minElementsNum].GetComponent<RectTransform>().anchoredPosition.y);
        }

        private void ScrollingElements(float position)
        {
            float newY = Mathf.Lerp(_scrollingPanel.anchoredPosition.y, position, Time.deltaTime * 1f);
            Vector2 newPosition = new Vector2(_scrollingPanel.anchoredPosition.x, newY);
            _scrollingPanel.anchoredPosition = newPosition;
        }

        public string GetResults()
        {
            return result;
        }

        public void SnapToElement(int element)
        {
            float deltaElementPositionY = _arrayOfElements[0].GetComponent<RectTransform>().rect.height * element;
            Vector2 newPosition = new Vector2(_scrollingPanel.anchoredPosition.x, -deltaElementPositionY);
            _scrollingPanel.anchoredPosition = newPosition;

        }

        public void ScrollUp()
        {
            float deltaUp = _arrayOfElements[0].GetComponent<RectTransform>().rect.height / 1.2f;
            Vector2 newPositionUp = new Vector2(_scrollingPanel.anchoredPosition.x, _scrollingPanel.anchoredPosition.y - deltaUp);
            _scrollingPanel.anchoredPosition = Vector2.Lerp(_scrollingPanel.anchoredPosition, newPositionUp, 1);
        }

        public void ScrollDown()
        {
            float deltaDown = _arrayOfElements[0].GetComponent<RectTransform>().rect.height / 1.2f;
            Vector2 newPositionDown = new Vector2(_scrollingPanel.anchoredPosition.x, _scrollingPanel.anchoredPosition.y + deltaDown);
            _scrollingPanel.anchoredPosition = newPositionDown;
        }
    }
}

源代码是上下滑动的,再上我改过之后的代码,左右滑动的;

/// Credit Mrs. YakaYocha 
/// Sourced from - https://www.youtube.com/channel/UCHp8LZ_0-iCvl-5pjHATsgw
/// Please donate: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RJ8D9FRFQF9VS

using UnityEngine.Events;

namespace UnityEngine.UI.Extensions
{
    [RequireComponent(typeof(ScrollRect))]
    [AddComponentMenu("Layout/Extensions/Vertical Scroller")]
    public class UIVerticalScrollerMove : MonoBehaviour
    {
        [Tooltip("Scrollable area (content of desired ScrollRect)")]
        public RectTransform _scrollingPanel;//展示面板
        [Tooltip("Elements to populate inside the scroller")]
        public GameObject[] _arrayOfElements;//长度元素
        [Tooltip("Center display area (position of zoomed content)")]
        public RectTransform _center;//位置
        [Tooltip("Select the item to be in center on start. (optional)")]
        public int StartingIndex = -1;//初始指针(外界提供)
        [Tooltip("Button to go to the next page. (optional)")]
        public GameObject ScrollLeftButton;//左按钮
        [Tooltip("Button to go to the previous page. (optional)")]
        public GameObject ScrollRightButton;//右按钮
        [Tooltip("Event fired when a specific item is clicked, exposes index number of item. (optional)")]
        public UnityEvent<int> ButtonClicked;//按钮点击


        private float[] distReposition;//长度改变
        private float[] distance;//长度列表
        //private int elementsDistance;
        private int minElementsNum;//最小元素数
        private int elementLength;//元素长度
        //private int elementHalfLength;
        private float deltaX;//移动x
        private string result;//结果

        public UIVerticalScrollerMove() { }//构造函数

        public UIVerticalScrollerMove(RectTransform scrollingPanel, GameObject[] arrayOfElements, RectTransform center)
        {
            _scrollingPanel = scrollingPanel;
            _arrayOfElements = arrayOfElements;
            _center = center;
        }


        //初始化启动
        public void Awake()
        {
            var scrollRect = GetComponent<ScrollRect>();//获取到排列
            if (!_scrollingPanel)
            {
                _scrollingPanel = scrollRect.content;//如果不是展示面板,获取该物体的可滚动的面板
            }
            if (!_center)//如果设置不成功,打印失败
            {
                Debug.LogError("Please define the RectTransform for the Center viewport of the scrollable area");
            }
            if (_arrayOfElements == null || _arrayOfElements.Length == 0)
            {
                var childCount = scrollRect.content.childCount;
                if (childCount > 0)
                {
                    _arrayOfElements = new GameObject[childCount];
                    for (int i = 0; i < childCount; i++)
                    {
                        _arrayOfElements[i] = scrollRect.content.GetChild(i).gameObject;
                    }                    
                }
            }//获取子物体的长度
        }

        //初始化启动
        public void Start()
        {
            if (_arrayOfElements.Length < 1)
            {
                Debug.Log("No child content found, exiting..");
                return;
            }//没有子物体的时候,打印寻找失败

            elementLength = _arrayOfElements.Length;
            distance = new float[elementLength];
            distReposition = new float[elementLength];//通过子物体的长度定义距离长度列表与移动长度列表

            //get distance between buttons
            //elementsDistance = (int)Mathf.Abs(_arrayOfElements[1].GetComponent<RectTransform>().anchoredPosition.y - _arrayOfElements[0].GetComponent<RectTransform>().anchoredPosition.y);
            deltaX = _arrayOfElements[0].GetComponent<RectTransform>().rect.width * elementLength / 3 * 2;
            Vector2 startPosition = new Vector2( -deltaX,_scrollingPanel.anchoredPosition.y);
            _scrollingPanel.anchoredPosition = startPosition;//获取到更改的按钮

            for (var i = 0; i < _arrayOfElements.Length; i++)
            {
                AddListener(_arrayOfElements[i], i);
            }//监听每个按钮上挂载的方法

            //如果左右按钮的话,分别监听不同的方法
            if (ScrollLeftButton)
                ScrollLeftButton.GetComponent<Button>().onClick.AddListener(() => { ScrollLeft(); });

            if (ScrollRightButton)
                ScrollRightButton.GetComponent<Button>().onClick.AddListener(() => { ScrollRight(); });
            
            //比较外界提供的初始指针并进行初始定位
            if (StartingIndex > -1)
            {
                StartingIndex = StartingIndex > _arrayOfElements.Length ? _arrayOfElements.Length - 1 : StartingIndex;
                SnapToElement(StartingIndex);
            }
        }

        //让该物体监听到自己所对应的事件
        private void AddListener(GameObject button, int index)
        {
            button.GetComponent<Button>().onClick.AddListener(() => DoSomething(index));
        }

        //index按钮对应的点击状态
        private void DoSomething(int index)
        {
            if (ButtonClicked != null)
            {
                ButtonClicked.Invoke(index);
            }
        }

        //逻辑更新
        public void Update()
        {
            if (_arrayOfElements.Length < 1)
            {
                return;
            }//子物体为空的时候返回

            for (var i = 0; i < elementLength; i++)
            {
                distReposition[i] = _center.GetComponent<RectTransform>().position.x - _arrayOfElements[i].GetComponent<RectTransform>().position.x;
                distance[i] = Mathf.Abs(distReposition[i]);

                //Magnifying effect
                float scale = Mathf.Max(0.7f, 1 / (1 + distance[i] / 200));
                _arrayOfElements[i].GetComponent<RectTransform>().transform.localScale = new Vector3(scale, scale, 1f);
            }//不断更新可滑动面板下面的物体下面的动态数列
            float minDistance = Mathf.Min(distance);//求出最小间距

            for (var i = 0; i < elementLength; i++)
            {
                _arrayOfElements[i].GetComponent<CanvasGroup>().interactable = false;
                if (minDistance == distance[i])
                {
                    minElementsNum = i;
                    _arrayOfElements[i].GetComponent<CanvasGroup>().interactable = true;
                    result = _arrayOfElements[i].GetComponentInChildren<Text>().text;
                }
            }//除了被选中的物体,其余物体都是不可交互的

            ScrollingElements(-_arrayOfElements[minElementsNum].GetComponent<RectTransform>().anchoredPosition.x);//不断向着新坐标移动
        }

        //不断移动坐标,保证向着目标点移动
        private void ScrollingElements(float position)
        {
            float newX= Mathf.Lerp(_scrollingPanel.anchoredPosition.x, position, Time.deltaTime * 1f);
            Vector2 newPosition = new Vector2(newX,_scrollingPanel.anchoredPosition.y);
            _scrollingPanel.anchoredPosition = newPosition;
        }

        public string GetResults()
        {
            return result;
        }

        //通过指针计算该物体在坐标栏下的位置
        public void SnapToElement(int element)
        {
            float deltaElementPositionX = _arrayOfElements[0].GetComponent<RectTransform>().rect.width * element;
            Vector2 newPosition = new Vector2(-deltaElementPositionX,_scrollingPanel.anchoredPosition.y);
            _scrollingPanel.anchoredPosition = newPosition;
        }

        //左右滑动
        public void ScrollLeft()
        {
            float deltaLeft = _arrayOfElements[0].GetComponent<RectTransform>().rect.width / 1.2f;
            Vector2 newPositionLeft = new Vector2(_scrollingPanel.anchoredPosition.x-deltaLeft, _scrollingPanel.anchoredPosition.y);
            _scrollingPanel.anchoredPosition = Vector2.Lerp(_scrollingPanel.anchoredPosition,newPositionLeft, 1);
        }

        public void ScrollRight()
        {
            float deltaRight = _arrayOfElements[0].GetComponent<RectTransform>().rect.width / 1.2f;
            Vector2 newPositionRight = new Vector2(_scrollingPanel.anchoredPosition.x+deltaRight, _scrollingPanel.anchoredPosition.y);
            _scrollingPanel.anchoredPosition = newPositionRight;
        }
    }
}

这是个插件里面的类库,不过核心逻辑可以用Unity来重写,以上都有注释。

最后是引用方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UI.Extensions;

public class ScrollingCalendarTest : MonoBehaviour {
	public RectTransform monthsScrollingPanel;
	public GameObject monthsButtonPrefab;
    private GameObject[] monthsButtons;
	public RectTransform monthCenter;
	
	private int monthsSet;
	
	UIVerticalScrollerMove monthsVerticalScroller;
	//Initialize Months
	//生成预制体
	private void InitializeMonths()
	{
		int[] months = new int[12];

		monthsButtons = new GameObject[months.Length];
		for (int i = 0; i < months.Length; i++)
		{
			string month = "";
			months[i] = i;

			GameObject clone = (GameObject)Instantiate(monthsButtonPrefab, new Vector3(i * 380,0,  0), Quaternion.Euler(new Vector3(0, 0, 0))) as GameObject;
			clone.transform.SetParent(monthsScrollingPanel, false);
			clone.transform.localScale = new Vector3(1, 1, 1);

			month = ""+i;

			clone.GetComponentInChildren<Text>().text = month;
			clone.name = "Month_" + months[i];
			clone.AddComponent<CanvasGroup>();
			monthsButtons[i] = clone;
		}
	}
	// Use this for initialization
        public void Awake()
        {
            InitializeMonths();

            //Yes Unity complains about this but it doesn't matter in this case.
            monthsVerticalScroller = new UIVerticalScrollerMove(monthsScrollingPanel, monthsButtons, monthCenter);

            monthsVerticalScroller.Start();
        }

        public void SetDate()
        {
//            monthsSet = int.Parse(inputFieldMonths.text) - 1;

            monthsVerticalScroller.SnapToElement(monthsSet);
        }

        void Update()
        {
            monthsVerticalScroller.Update();

            string monthString = monthsVerticalScroller.GetResults();

        }


        public void MonthsScrollUp()
        {
            monthsVerticalScroller.ScrollLeft();
        }

        public void MonthsScrollDown()
        {
            monthsVerticalScroller.ScrollRight();
        }

}

效果与引用:

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值