欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)效果的示例詳解

 更新時(shí)間:2022年12月09日 08:58:54   作者:CoderZ1010  
這篇文章主要為大家詳細(xì)介紹了如何利用Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)的效果,文中的實(shí)現(xiàn)步驟講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下

簡(jiǎn)介

功能需求如圖所示,點(diǎn)擊下一個(gè)按鈕,所有卡片向右滾動(dòng),其中最后一張需要變更為最前面的一張,點(diǎn)擊上一個(gè)按鈕,所有卡片向左滾動(dòng),最前面的一張需要變更為最后一張,實(shí)現(xiàn)循環(huán)滾動(dòng)效果。

最中間的一張表示當(dāng)前選中項(xiàng),變更為選中項(xiàng)的滾動(dòng)過(guò)程中,需要逐漸放大到指定值,相反則需要恢復(fù)到默認(rèn)大小。

實(shí)現(xiàn)思路:

  • 定義卡片的擺放規(guī)則;
  • 調(diào)整卡片的層級(jí)關(guān)系;
  • 調(diào)整卡片的尺寸大??;
  • 卡片向指定方向移動(dòng),動(dòng)態(tài)調(diào)整位置、大小、層級(jí)關(guān)系。

定義卡片的擺放規(guī)則

第一張卡片放在正中間,其余卡片分成兩部分分別放在左右兩側(cè),因此如果卡片數(shù)量為奇數(shù),則左右兩側(cè)卡片數(shù)量一致,如果卡片數(shù)量為偶數(shù),多出的一張需要放到左側(cè)或者右側(cè),這里我們定義為放到右側(cè)。

卡片擺放的順序如下圖所示,在遍歷生成時(shí)會(huì)判斷當(dāng)前索引是否小等于卡片數(shù)量/2,是則將卡片生成在索引值*指定卡片間距的位置上,否則將其生成在(索引值-卡片數(shù)量)*指定卡片間距的位置上。

代碼實(shí)現(xiàn):

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

public class LoopScrollView : MonoBehaviour
{
    [SerializeField] private Texture[] roomTextures; //所有卡片
    [SerializeField] private GameObject itemPrefab; //列表項(xiàng)預(yù)制體
    [SerializeField] private Transform itemParent; //列表項(xiàng)的父級(jí),將卡片生成到該物體下
    [SerializeField] private float interval = 450f; //卡片之間的間距

    private void Start()
    {
        for (int i = 0; i < roomTextures.Length; i++)
        {
            var tex = roomTextures[i];
            var instance = Instantiate(itemPrefab);
            instance.SetActive(true);
            instance.transform.SetParent(itemParent, false);
            instance.GetComponent<RawImage>().texture = tex;
            instance.name = i.ToString();

            //坐標(biāo)位置
            (instance.transform as RectTransform).anchoredPosition3D = Vector3.right * interval
                * (i <= roomTextures.Length / 2 ? i : (i - roomTextures.Length));
        }
    }
}

調(diào)整卡片的層級(jí)關(guān)系

卡片的層級(jí)關(guān)系如圖所示,第一張也就是中間的照片(編號(hào)0)需要在最上層,向左、向右逐漸遮擋下層,在Hierarchy層級(jí)窗口的表現(xiàn)則是編號(hào)0的卡片在最下方,編號(hào)1卡片在編號(hào)2卡片下方以遮擋編號(hào)2卡片,編號(hào)4卡片在編號(hào)3卡片下方以遮擋編號(hào)3卡片。

在遍歷生成卡片時(shí)判斷當(dāng)前索引值是否小等于卡片數(shù)量/2,是則在層級(jí)中將其插入到最上方,也就是SiblingIndex=0,否則將其插入在第一張卡片之上,第一張卡片始終在最下方,也就是說(shuō)插入為倒數(shù)第二個(gè),即SiblingIndex=父節(jié)點(diǎn)的子物體數(shù)量-2。

代碼如下:

//層級(jí)關(guān)系
instance.transform.SetSiblingIndex(i <= roomTextures.Length / 2 ? 0 : itemParent.childCount - 2);

調(diào)整卡片的尺寸大小

大小的調(diào)整比較簡(jiǎn)單,只需要將第一張卡片放大一定倍數(shù)即可。

//大小
instance.transform.localScale = (i == 0 ? 1.2f : 1f) * Vector3.one;

至此已經(jīng)完成了卡片的生成,但是如何在點(diǎn)擊上一個(gè)、下一個(gè)按鈕時(shí)動(dòng)態(tài)調(diào)整所有卡片的坐標(biāo)、層級(jí)和大小才是關(guān)鍵。

動(dòng)態(tài)調(diào)整位置、層級(jí)和大小

移動(dòng)動(dòng)畫

首先為每張卡片添加腳本,用于實(shí)現(xiàn)卡片的移動(dòng)邏輯,使用插值的形式來(lái)實(shí)現(xiàn)動(dòng)畫過(guò)程,假設(shè)動(dòng)畫所需時(shí)長(zhǎng)為0.5秒,使用變量float類型變量timer來(lái)計(jì)時(shí),自增Time.deltaTime * 2以使其在0.5秒內(nèi)的取值從0增加為1,并使用Mathf.Clamp01來(lái)鉗制其取值范圍不要超過(guò)1。

代碼如下:

using UnityEngine;

public class LoopScrollViewItem : MonoBehaviour
{
    private RectTransform rectTransform;
    private int index; //用于記錄當(dāng)前所在位置
    private Vector3 cacheScale; //開始移動(dòng)時(shí)的大小
    private Vector3 cacheAnchorPosition3d; //開始移動(dòng)時(shí)的坐標(biāo)
    private Vector3 targetAnchorPostion3D; //目標(biāo)坐標(biāo)
    private int targetSiblingIndex; //目標(biāo)層級(jí)
    private bool isMoving; //是否正在移動(dòng)標(biāo)識(shí)
    private float timer; //計(jì)時(shí)
    private bool last; //是否為最右側(cè)的那張卡片

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    public int Index
    {
        get
        {
            return index;
        }
        set
        {
            if (index != value)
            {
                index = value;
            }
        }
    }

    private void Update()
    {
        if (isMoving)
        {
            timer += Time.deltaTime * 2f; 
            timer = Mathf.Clamp01(timer);
            if (timer >= .2f)
            {
                transform.SetSiblingIndex(targetSiblingIndex);
            }
            rectTransform.anchoredPosition3D = Vector3.Lerp(cacheAnchorPosition3d, targetAnchorPostion3D, last ? 1f : timer);
            transform.localScale = Vector3.Lerp(cacheScale, (index == 0 ? 1.3f : 1f) * Vector3.one, last ? 1f : timer);
            if (timer == 1f)
            {
                isMoving = false;
            }
        }
    }

    public void Move(LoopScrollViewData data, bool last)
    {
        timer = 0f;
        targetAnchorPostion3D = data.AnchorPosition3D;
        targetSiblingIndex = data.SiblingIndex;
        cacheAnchorPosition3d = rectTransform.anchoredPosition3D;
        cacheScale = transform.localScale;
        isMoving = true;
        this.last = last;
    }
}

其中last變量用于標(biāo)識(shí)是否為最右側(cè)的那張卡片,如果是,使其立即變?yōu)樽钭髠?cè)的卡片,不表現(xiàn)動(dòng)畫過(guò)程,目的是為了防止如下圖所示,卡片從最右側(cè)移動(dòng)到最左側(cè)的穿幫現(xiàn)象:

在生成卡片時(shí),為卡片物體添加該腳本,并添加到列表中進(jìn)行緩存,同時(shí),定義一個(gè)用于存儲(chǔ)各編號(hào)對(duì)應(yīng)的層級(jí)和坐標(biāo)的數(shù)據(jù)結(jié)構(gòu),代碼如下:

using UnityEngine;

public class LoopScrollViewData
{
    public int SiblingIndex { get; private set; }

    public Vector3 AnchorPosition3D { get; private set; }

    public LoopScrollViewData(int siblingIndex, Vector3 anchorPosition3D)
    {
        SiblingIndex = siblingIndex;
        AnchorPosition3D = anchorPosition3D;
    }
}
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class LoopScrollView : MonoBehaviour
{
    [SerializeField] private Texture[] roomTextures; //所有卡片
    [SerializeField] private GameObject itemPrefab; //列表項(xiàng)預(yù)制體
    [SerializeField] private Transform itemParent; //列表項(xiàng)的父級(jí),將卡片生成到該物體下
    [SerializeField] private float interval = 400f; //卡片之間的間距
    
    //生成的卡片列表
    private readonly List<LoopScrollViewItem> itemList = new List<LoopScrollViewItem>();
    //字典用于存儲(chǔ)各位置對(duì)應(yīng)的卡片層級(jí)和坐標(biāo)
    private readonly Dictionary<int, LoopScrollViewData> map = new Dictionary<int, LoopScrollViewData>();

    private void Start()
    {
        for (int i = 0; i < roomTextures.Length; i++)
        {
            var tex = roomTextures[i];
            var instance = Instantiate(itemPrefab);
            instance.SetActive(true);
            instance.transform.SetParent(itemParent, false);
            instance.GetComponent<RawImage>().texture = tex;
            instance.name = i.ToString();

            //坐標(biāo)位置
            (instance.transform as RectTransform).anchoredPosition3D = Vector3.right * interval
                * (i <= roomTextures.Length / 2 ? i : (i - roomTextures.Length));
            //層級(jí)關(guān)系
            instance.transform.SetSiblingIndex(i <= roomTextures.Length / 2 ? 0 : itemParent.childCount - 2);
            //大小
            instance.transform.localScale = (i == 0 ? 1.2f : 1f) * Vector3.one;

            var item = instance.AddComponent<LoopScrollViewItem>();
            item.Index = i;
            itemList.Add(item);
        }
        for (int i = 0; i < itemList.Count; i++)
        {
            var item = itemList[i];
            map.Add(i, new LoopScrollViewData(item.transform.GetSiblingIndex(), (item.transform as RectTransform).anchoredPosition3D));
        }
    }
}

按鈕事件

在生成卡片時(shí),記錄了卡片當(dāng)前的編號(hào),以及各編號(hào)對(duì)應(yīng)的層級(jí)和位置,在點(diǎn)擊下一個(gè)、上一個(gè)按鈕時(shí),只需要根據(jù)卡片當(dāng)前的編號(hào)+1-1來(lái)獲取目標(biāo)層級(jí)和位置即可。

編號(hào)自增后,如果等于卡片的數(shù)量,表示當(dāng)前卡片已經(jīng)是列表中最后一個(gè),需要將其編號(hào)設(shè)為0,相反,當(dāng)編號(hào)自減后,如果小于0,表示當(dāng)前卡片已經(jīng)是列表中第一個(gè),需要將其編號(hào)設(shè)為列表長(zhǎng)度-1,以實(shí)現(xiàn)循環(huán)。

完整代碼:

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

public class LoopScrollView : MonoBehaviour
{
    [SerializeField] private Texture[] roomTextures; //所有卡片
    [SerializeField] private GameObject itemPrefab; //列表項(xiàng)預(yù)制體
    [SerializeField] private Transform itemParent; //列表項(xiàng)的父級(jí),將卡片生成到該物體下
    [SerializeField] private Button prevButton; //上一個(gè)按鈕
    [SerializeField] private Button nextButton; //下一個(gè)按鈕
    [SerializeField] private float interval = 400f; //卡片之間的間距
    
    //生成的卡片列表
    private readonly List<LoopScrollViewItem> itemList = new List<LoopScrollViewItem>();
    //字典用于存儲(chǔ)各位置對(duì)應(yīng)的卡片層級(jí)和坐標(biāo)
    private readonly Dictionary<int, LoopScrollViewData> map = new Dictionary<int, LoopScrollViewData>();

    private void Start()
    {
        for (int i = 0; i < roomTextures.Length; i++)
        {
            var tex = roomTextures[i];
            var instance = Instantiate(itemPrefab);
            instance.SetActive(true);
            instance.transform.SetParent(itemParent, false);
            instance.GetComponent<RawImage>().texture = tex;
            instance.name = i.ToString();

            //坐標(biāo)位置
            (instance.transform as RectTransform).anchoredPosition3D = Vector3.right * interval
                * (i <= roomTextures.Length / 2 ? i : (i - roomTextures.Length));
            //層級(jí)關(guān)系
            instance.transform.SetSiblingIndex(i <= roomTextures.Length / 2 ? 0 : itemParent.childCount - 2);
            //大小
            instance.transform.localScale = (i == 0 ? 1.2f : 1f) * Vector3.one;

            var item = instance.AddComponent<LoopScrollViewItem>();
            item.Index = i;
            itemList.Add(item);
        }
        for (int i = 0; i < itemList.Count; i++)
        {
            var item = itemList[i];
            map.Add(i, new LoopScrollViewData(item.transform.GetSiblingIndex(), (item.transform as RectTransform).anchoredPosition3D));
        }

        //添加按鈕點(diǎn)擊事件
        nextButton.onClick.AddListener(OnNextButtonClick);
        prevButton.onClick.AddListener(OnPrevButtonClick);
    }

    //下一個(gè)按鈕點(diǎn)擊事件
    private void OnNextButtonClick()
    {
        for (int i = 0; i < itemList.Count; i++)
        {
            var item = itemList[i];
            bool last = item.Index == itemList.Count / 2;
            int index = item.Index + 1;
            index = index >= itemList.Count ? 0 : index;
            item.Index = index;
            item.Move(map[index], last);
        }
    }
    //上一個(gè)按鈕點(diǎn)擊事件
    private void OnPrevButtonClick()
    {
        for (int i = 0; i < itemList.Count; i++)
        {
            var item = itemList[i];
            int index = item.Index - 1;
            index = index < 0 ? itemList.Count - 1 : index;
            item.Index = index;
            item.Move(map[index], false);
        }
    }
}

到此這篇關(guān)于Unity實(shí)現(xiàn)卡片循環(huán)滾動(dòng)效果的示例詳解的文章就介紹到這了,更多相關(guān)Unity卡片循環(huán)滾動(dòng)效果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C# 如何使用OpcUaHelper讀寫OPC服務(wù)器

    C# 如何使用OpcUaHelper讀寫OPC服務(wù)器

    這篇文章給大家介紹C# 如何使用OpcUaHelper讀寫OPC服務(wù)器,本文通過(guò)圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-12-12
  • C# 三種序列化方法分享

    C# 三種序列化方法分享

    這篇文章主要介紹了C# 三種序列化方法,需要的朋友可以參考下
    2014-02-02
  • c#?chart縮放,局部放大問(wèn)題

    c#?chart縮放,局部放大問(wèn)題

    這篇文章主要介紹了c#?chart縮放,局部放大問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • C# 輸出字符串到文本文件中的實(shí)現(xiàn)代碼

    C# 輸出字符串到文本文件中的實(shí)現(xiàn)代碼

    本文通過(guò)一個(gè)簡(jiǎn)單的代碼給大家介紹C# 輸出字符串到文本文件中,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • c#實(shí)現(xiàn)抓取高清美女妹紙圖片

    c#實(shí)現(xiàn)抓取高清美女妹紙圖片

    本文給大家分享的是一則使用c#實(shí)現(xiàn)抓取網(wǎng)絡(luò)高清美女妹紙圖片的代碼,這么好的東西,當(dāng)然不能獨(dú)享,推薦給小伙伴們。
    2015-03-03
  • C#中執(zhí)行SQL的幾種方法講解

    C#中執(zhí)行SQL的幾種方法講解

    這篇文章介紹了C#中執(zhí)行SQL的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • 基于C#實(shí)現(xiàn)電腦系統(tǒng)掛機(jī)鎖

    基于C#實(shí)現(xiàn)電腦系統(tǒng)掛機(jī)鎖

    這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)電腦系統(tǒng)掛機(jī)鎖,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • c#委托學(xué)習(xí)示例分享

    c#委托學(xué)習(xí)示例分享

    委托是一個(gè)類,它定義了方法的類型,使得可以將方法當(dāng)作另一個(gè)方法的參數(shù)來(lái)進(jìn)行傳遞,這種將方法動(dòng)態(tài)地賦給參數(shù)的做法,可以避免在程序中大量使用If-Else(Switch)語(yǔ)句,同時(shí)使得程序具有更好的可擴(kuò)展性,下面是c#委托示例
    2014-03-03
  • 基于Unity實(shí)現(xiàn)3D版2048游戲的示例代碼

    基于Unity實(shí)現(xiàn)3D版2048游戲的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Unity實(shí)現(xiàn)簡(jiǎn)易的3D版2048游戲,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下
    2023-02-02
  • C#簡(jiǎn)單操作MongoDB的步驟全紀(jì)錄

    C#簡(jiǎn)單操作MongoDB的步驟全紀(jì)錄

    最近花了不少時(shí)間研究學(xué)習(xí)了MongoDB數(shù)據(jù)庫(kù)的相關(guān)知識(shí),下面這篇文章主要給大家介紹了關(guān)于C#簡(jiǎn)單操作MongoDB的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧
    2018-09-09

最新評(píng)論