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

Unity ScrollView實現(xiàn)無限循環(huán)效果

 更新時間:2021年07月27日 10:27:26   作者:司軍禮  
這篇文章主要為大家詳細(xì)介紹了Unity ScrollView實現(xiàn)無限循環(huán)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Unity ScrollView實現(xiàn)無限循環(huán)效果的具體代碼,供大家參考,具體內(nèi)容如下

在Unity引擎中ScrollView組件是一個使用率比較高的組件,該組件能上下或者左右拖動的UI列表,背包、展示多個按鈕等情況的時候會用到,在做排行榜類似界面時,item非常多,可能有幾百個,一次創(chuàng)建這么多GameObject是非??ǖ?。為此,使用只創(chuàng)建可視區(qū)一共顯示的個數(shù),加上后置準(zhǔn)備個數(shù)。

由于ScrollView有兩種滾動方式,水平滾動或者垂直滾動,所以我創(chuàng)建了ScrollBase基類,和HorizontalScroll子類及VerticalScroll子類,在父類中設(shè)定了公共的抽象方法OnDrawView—繪制顯示區(qū)的方法;CreateItem----創(chuàng)建Item的方法;Update----滾動狀態(tài)下實時更新Item的位置。

ScrollBase基類

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

public enum MoveType
{
    UP,
    DOWN,
    LEFT,
    RIGHT,
    STOP
}

public abstract class ScrollBase
{

    public ItemArray<ItemData> items;
    public ScrollViewLoop scrollLoop;
    public float viewHeight;
    public float viewWidth;
    public float contentHeight;
    public float contentWidth;
    public RectTransform rectTransform;
    public ScrollRect scrollRect;
    public MoveType type;

    public float item_width;//每個Item的寬度
    public float item_height;//每個Item的高度
    public int viewNum;//顯示區(qū)顯示的個數(shù)
    public int addNum;//后置準(zhǔn)備個數(shù)
    public int itemNum;//總共需要多少Item的滾動
    public float spaceY;//垂直Item間隔
    public float spaceX;//水平Item間隔

    public ScrollBase(ScrollViewLoop _scrollLoop, bool isCreateItem = true)
    {
        scrollLoop = _scrollLoop;
        rectTransform = scrollLoop.GetComponent<RectTransform>();
        scrollRect = scrollLoop.GetComponent<ScrollRect>();
        if (!scrollRect)
        {
            scrollRect = scrollLoop.gameObject.AddComponent<ScrollRect>();
        }
        item_width = scrollLoop.item_width;
        item_height = scrollLoop.item_height;
        viewNum = scrollLoop.viewNum;
        addNum = scrollLoop.addNum;
        itemNum = scrollLoop.itemNum;
        spaceY = scrollLoop.spaceY;
        spaceX = scrollLoop.spaceX;

        OnDrawView();
        if (isCreateItem)
        {
            CreateItem();
        }

    }

    public abstract void OnDrawView();

    public abstract void CreateItem();

    public abstract void Update();

}

ScrollViewLoop控制類

這個屬性類需要掛載在ScrollRect物體身上,然后在面板上進(jìn)行屬性配置

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


public class ItemData
{
    public RectTransform itemRect;
    public int index;
}

public class ScrollViewLoop : MonoBehaviour
{
    public GameObject itemPrefab;
    [Header("每個Item的寬度")]
    public float item_width;
    [Header("每個Item的高度")]
    public float item_height;
    [Header("顯示區(qū)顯示幾個Item")]
    public int viewNum = 6;
    [Header("顯示區(qū)外多復(fù)制幾個Item")]
    public int addNum = 2;
    [Header("總共需要多少Item")]
    public int itemNum = 100;
    [Header("Item之間的垂直距離")]
    public float spaceY = 2;
    public float spaceX = 2;
    public delegate void ItemChange(ItemData itemData);
    public event ItemChange OnChange;//Item位置改變時調(diào)用的事件
    [Header("是否是橫向滑動")]
    public bool isHorizontal = false;
    ScrollBase scrollBase;

    void Start()
    {

        if (isHorizontal)
        {
            scrollBase = new HorizontalScroll(this);
        }
        else
        {
            scrollBase = new VerticalScroll(this);
        }

    }

    public void UseOnChange(ItemData itemData)
    {
        OnChange?.Invoke(itemData);
    }
   

    //ScrollRect滾動
    void Update()
    {
        if (scrollBase != null)
        {
            scrollBase.Update();
        }
    }

}

ItemArray

我們實現(xiàn)無限循環(huán)的核心思想是,當(dāng)滾動框向左移動時,就判斷左邊的第一個Item距離顯示框左邊框的距離,是否大于Item水平間隔*0.5+Item的寬度,如果大于則把第一個Item放到最后的位置,當(dāng)滾動框向右移動時就判斷右邊的Item距離右邊框的距離情況,這樣我們就可以在顯示區(qū)域一直看到有Item的規(guī)則顯示,所以我定制了一個泛型容器類,這個類存放所有的Item信息,當(dāng)我們?nèi)〉谝粋€Item時自動把第一個Item放到最后,當(dāng)我們?nèi)∽詈笠粋€Item時自動把最后的一個Item放到最前面。

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

/// <summary>
/// Item集合類
/// </summary>
/// <typeparam name="T"></typeparam>
public class ItemArray<T> where T : ItemData
{
    List<T> list;
    public int count
    {
        get
        {
            return list.Count;
        }
    }

    public ItemArray()
    {
        list = new List<T>();
    }

    public ItemArray(T[] ts)
    {
        if (ts == null)
        {
            return;
        }
        for (int i = 0; i < ts.Length; i++)
        {
            list.Add(ts[i]);
        }
    }

    /// <summary>
    /// 添加一個元素
    /// </summary>
    /// <param name="t"></param>
    public void AddItem(T t)
    {
        list.Add(t);
    }

    public T GetFirst()
    {
        if (list.Count == 0)
        {
            return default(T);
        }
        T t = list[0];
        list.RemoveAt(0);
        t.index = list[list.Count - 1].index + 1;
        list.Add(t);
        return t;
    }

    public T GetLast()
    {
        if (list.Count == 0)
        {
            return default(T);
        }
        T t = list[list.Count - 1];
        list.RemoveAt(list.Count - 1);
        t.index = list[0].index - 1;
        list.Insert(0, t);
        return t;
    }

    public T[] GetArray()
    {
        T[] ts = new T[list.Count];
        for (int i = 0; i < list.Count; i++)
        {
            ts[i] = list[i];
        }
        return ts;
    }

    public T this[int index]
    {
        get
        {
            return list[index];
        }
    }

}

HorizontalScroll子類及VerticalScroll子類

ScrollView無限循環(huán)的核心功能代碼都在這兩個子類中

HorizontalScroll子類

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

public class HorizontalScroll : ScrollBase
{
    public HorizontalScroll(ScrollViewLoop _scrollLoop, bool isCreateItem = true) : base(_scrollLoop, isCreateItem)
    {
        scrollRect.horizontal = true;
        scrollRect.vertical = false;
    }

    public override void CreateItem()
    {
        items = new ItemArray<ItemData>();
        for (int i = 0; i < viewNum + addNum; i++)
        {
            GameObject item = GameObject.Instantiate(scrollLoop.itemPrefab);
            RectTransform itemRect = item.GetComponent<RectTransform>();
            ItemData data = new ItemData();
            data.itemRect = itemRect;
            data.index = i;
            items.AddItem(data);
            scrollLoop.UseOnChange(data);
            itemRect.sizeDelta = new Vector2(item_width, item_height);
            itemRect.anchorMin = new Vector2(0, 1);
            itemRect.anchorMax = new Vector2(0, 1);
            itemRect.pivot = new Vector2(0, 1);
            itemRect.localScale = Vector2.one;
            item.transform.parent = scrollRect.content;
            item.transform.localPosition = new Vector3(i * (item_width + spaceX), 0, 0);
        }
    }

    void RewindItemPos()
    {
        int index = Mathf.FloorToInt(Mathf.Abs(scrollRect.content.localPosition.x) / (item_width + spaceX));
        for (int i = 0; i < items.count; i++)
        {
            RectTransform itemRect = items[i].itemRect;
            items[i].index = index;
            scrollLoop.UseOnChange(items[i]);
            itemRect.transform.localPosition = new Vector3(items[i].index * (item_width + spaceX), 0, 0);
            index++;
        }
    }


    public override void OnDrawView()
    {
        SetRectTransform(rectTransform);
        rectTransform.sizeDelta = new Vector2(item_width * viewNum + (viewNum - 1) * spaceX, item_height);
        SetRectTransform(scrollRect.viewport);
        viewHeight = scrollLoop.item_height;
        viewWidth = viewNum * item_width + (viewNum - 1) * spaceX;
        scrollRect.viewport.sizeDelta = new Vector2(viewWidth, viewHeight);
        scrollRect.viewport.localPosition = Vector3.zero;
        SetRectTransform(scrollRect.content);
        contentHeight = item_height;
        contentWidth = itemNum * item_width + (itemNum - 1) * spaceX;
        scrollRect.content.sizeDelta = new Vector2(contentWidth, contentHeight);
        scrollRect.content.localPosition = Vector3.zero;
    }

    public void SetRectTransform(RectTransform rect)
    {
        rect.anchorMin = new Vector2(0, 0.5f);
        rect.anchorMax = new Vector2(0, 0.5f);
        rect.pivot = new Vector2(0, 1);
        rect.localScale = Vector2.one;
    }

    float lastX = 0;
    MoveType lastMoveType = MoveType.STOP;
    public override void Update()
    {
        float x = scrollRect.content.localPosition.x;
        if (x > lastX)
        {
            type = MoveType.RIGHT;
        }
        else if (x < lastX)
        {
            type = MoveType.LEFT;
        }
        else
        {
            type = MoveType.STOP;
            if (lastMoveType != type)
            {
                Debug.Log("重置位置");
                RewindItemPos();
            }
        }
        if (type == MoveType.LEFT)//向左滑動
        {
            if (items[items.count - 1].index == itemNum - 1)
            {
                return;
            }
            float firstItemX = items[0].itemRect.localPosition.x;
            if (-x - firstItemX - item_width >= spaceX * 0.5f)
            {
                float lastItemX = items[items.count - 1].itemRect.localPosition.x;
                ItemData firstItem = items.GetFirst();
                firstItem.itemRect.localPosition = new Vector3(lastItemX + spaceX + item_width, 0, 0);
                if (firstItem.index < itemNum)
                {
                    scrollLoop.UseOnChange(firstItem);
                }
            }
        }
        else if (type == MoveType.RIGHT)//向右滑動
        {
            if (items[0].index == 0)
            {
                return;
            }
            float lastItemX = items[items.count - 1].itemRect.localPosition.x;
            if (lastItemX + x - viewWidth >= spaceX * 0.5f)
            {
                float firstItemX = items[0].itemRect.localPosition.x;
                ItemData lastItem = items.GetLast();
                lastItem.itemRect.localPosition = new Vector3(firstItemX - spaceX - item_width, 0, 0);
                if (lastItem.index >= 0)
                {
                    scrollLoop.UseOnChange(lastItem);
                }
            }
        }
        lastMoveType = type;
        lastX = x;
    }
}

VerticalScroll子類

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

public class VerticalScroll : ScrollBase
{

    public VerticalScroll(ScrollViewLoop _scrollLoop, bool isCreateItem = true) : base(_scrollLoop, isCreateItem)
    {
        scrollRect.horizontal = false;
        scrollRect.vertical = true;
    }

    public override void CreateItem()
    {
        items = new ItemArray<ItemData>();
        for (int i = 0; i < viewNum + addNum; i++)
        {
            GameObject item = GameObject.Instantiate(scrollLoop.itemPrefab);
            RectTransform itemRect = item.GetComponent<RectTransform>();
            ItemData data = new ItemData();
            data.itemRect = itemRect;
            data.index = i;
            items.AddItem(data);
            scrollLoop.UseOnChange(data);
            itemRect.sizeDelta = new Vector2(item_width, item_height);
            itemRect.anchorMin = new Vector2(0, 1);
            itemRect.anchorMax = new Vector2(0, 1);
            itemRect.pivot = new Vector2(0, 1);
            itemRect.localScale = Vector2.one;
            item.transform.parent = scrollRect.content;
            item.transform.localPosition = new Vector3(0, (-i) * (item_height + spaceY), 0);
        }
    }

    void RewindItemPos()
    {
        int index = Mathf.FloorToInt(Mathf.Abs(scrollRect.content.localPosition.y) / (item_height + spaceY));
        for (int i = 0; i < items.count; i++)
        {
            RectTransform itemRect = items[i].itemRect;
            items[i].index = index;
            scrollLoop.UseOnChange(items[i]);
            itemRect.transform.localPosition = new Vector3(0, (-items[i].index) * (item_height + spaceY), 0);
            index++;
        }
    }

    public override void OnDrawView()
    {
        SetRectTransform(rectTransform);
        rectTransform.sizeDelta = new Vector2(item_width, viewNum * item_height + (viewNum - 1) * spaceY);
        SetRectTransform(scrollRect.viewport);
        viewHeight = viewNum * item_height + (viewNum - 1) * spaceY;
        scrollRect.viewport.sizeDelta = new Vector2(item_width, viewHeight);
        scrollRect.viewport.localPosition = Vector3.zero;
        SetRectTransform(scrollRect.content);
        contentHeight = itemNum * item_height + (itemNum - 1) * spaceY;
        scrollRect.content.sizeDelta = new Vector2(item_width, contentHeight);
        scrollRect.content.localPosition = Vector3.zero;
    }

    public void SetRectTransform(RectTransform rect)
    {
        rect.anchorMin = new Vector2(0.5f, 1);
        rect.anchorMax = new Vector2(0.5f, 1);
        rect.pivot = new Vector2(0, 1);
        rect.localScale = Vector2.one;
    }

    float lastY = 0;
    MoveType lastMoveType = MoveType.STOP;
    public override void Update()
    {
        float y = scrollRect.content.localPosition.y;
        if (y > lastY)
        {
            type = MoveType.UP;
        }
        else if (y < lastY)
        {
            type = MoveType.DOWN;
        }
        else
        {
            type = MoveType.STOP;
            if (lastMoveType != type)
            {
                RewindItemPos();
            }
        }
        if (type == MoveType.UP)//向上滑動
        {

            if (items[items.count - 1].index == itemNum - 1)
            {
                return;
            }
            float firstItemY = items[0].itemRect.localPosition.y;
            if (firstItemY - item_height + y >= spaceY * 0.5f)
            {
                float lastItemY = items[items.count - 1].itemRect.localPosition.y;
                ItemData firstItem = items.GetFirst();
                firstItem.itemRect.localPosition = new Vector3(0, lastItemY - spaceY - item_height, 0);
                if (firstItem.index < itemNum)
                {
                    scrollLoop.UseOnChange(firstItem);
                }
            }
        }
        else if (type == MoveType.DOWN)//向下滑動
        {
            if (items[0].index == 0)
            {
                return;
            }
            float lastItemY = items[items.count - 1].itemRect.localPosition.y;
            if (-lastItemY - y - viewHeight >= spaceY * 0.5f)
            {
                float firstItemY = items[0].itemRect.localPosition.y;
                ItemData lastItem = items.GetLast();
                lastItem.itemRect.localPosition = new Vector3(0, firstItemY + spaceY + item_height, 0);
                if (lastItem.index >= 0)
                {
                    scrollLoop.UseOnChange(lastItem);
                }
            }

        }
        lastMoveType = type;
        lastY = y;
    }
}

編輯器拓展

這一步我們進(jìn)行編輯器的拓展,根據(jù)ScrollViewLoop控制類面板上的數(shù)據(jù)我們在未運行的狀態(tài)下改變ScrollView的顯示區(qū)域,這樣更利于我們的可視化排版。

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

[CustomEditor(typeof(ScrollViewLoop))]
public class ScrollLopEditor : Editor
{
    ScrollViewLoop scrollLoop;
    private RectTransform scrollRectTransfrom;
    private ScrollRect scrollRect;
    private void OnEnable()
    {
        scrollLoop = target as ScrollViewLoop;
        scrollRectTransfrom = scrollLoop.GetComponent<RectTransform>();
        scrollRect = scrollLoop.GetComponent<ScrollRect>();

    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        bool isBtn = GUILayout.Button("編輯ScrollView顯示區(qū)大小");
        if (isBtn)
        {
            if (scrollLoop.isHorizontal)
            {
                ScrollBase scrollBase = new HorizontalScroll(scrollLoop, false);
            }
            else
            {
                ScrollBase scrollBase = new VerticalScroll(scrollLoop, false);
            }
        }
    }


}

測試

測試一下功能效果

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

public class Test : MonoBehaviour
{
    public ScrollViewLoop sl;

    private void Start()
    {
        sl.OnChange += Sl_OnChange;
    }

    //Item位置改變時自動改變Item展示內(nèi)容
    private void Sl_OnChange(ItemData itemData)
    {
        itemData.itemRect.GetChild(0).GetComponent<Text>().text = "ITEM"+itemData.index;
    }
}

面板顯示如下:

運行效果如下(本來想放一段視頻的,遺憾的是沒能成功操作,尷尬):

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 利用MySqlBulkLoader實現(xiàn)批量插入數(shù)據(jù)的示例詳解

    利用MySqlBulkLoader實現(xiàn)批量插入數(shù)據(jù)的示例詳解

    MySQLBulkLoader是MySQL?Connector/Net類中的一個類,用于包裝MySQL語句。本文將利用MySqlBulkLoader實現(xiàn)批量插入數(shù)據(jù)功能,感興趣的可以了解一下
    2022-06-06
  • 用Linq從一個集合選取幾列得到一個新的集合(可改列名)

    用Linq從一個集合選取幾列得到一個新的集合(可改列名)

    這篇文章主要介紹了用Linq從一個集合選取幾列得到一個新的集合(可改列名),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • .net使用cap實現(xiàn)消息異步處理

    .net使用cap實現(xiàn)消息異步處理

    CAP 是一個基于 .NET Standard 的 C# 庫,它是一種處理分布式事務(wù)的解決方案,同樣具有 EventBus 的功能,它具有輕量級、易使用、高性能等特點,本文給大家介紹了.net下使用cap實現(xiàn)消息異步處理,需要的朋友可以參考下
    2024-05-05
  • WPF+SkiaSharp實現(xiàn)自繪拖曳小球

    WPF+SkiaSharp實現(xiàn)自繪拖曳小球

    WPF的拖曳效果,基本配置一下,就可以了,但是自繪的話,就得自己控制。本文將利用WPF+SkiaSharp實現(xiàn)自繪拖曳小球,感興趣的可以動手嘗試一下
    2022-07-07
  • C#并發(fā)編程入門教程之概述

    C#并發(fā)編程入門教程之概述

    這篇文章主要給大家介紹了關(guān)于C#并發(fā)編程之概述的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • C# wx獲取token的基本方法

    C# wx獲取token的基本方法

    這篇文章主要為大家詳細(xì)介紹了C# wx獲取token的基本方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • C#實現(xiàn)發(fā)送郵件的三種方法

    C#實現(xiàn)發(fā)送郵件的三種方法

    這篇文章主要介紹了C#實現(xiàn)發(fā)送郵件的三種方法,實例講述了Localhost,SMTP與SSL-SMTP三種實現(xiàn)方法,對于C#項目開發(fā)有不錯的借鑒價值,需要的朋友可以參考下
    2014-11-11
  • 基于C#實現(xiàn)的多邊形沖突檢測實例

    基于C#實現(xiàn)的多邊形沖突檢測實例

    這篇文章主要給大家介紹了基于C#實現(xiàn)的多邊形沖突檢測的相關(guān)資料,文中介紹的方法并未使用第三方類庫,可以完美解決這個問題,需要的朋友可以參考下
    2021-07-07
  • C#不可變類型深入解析

    C#不可變類型深入解析

    這篇文章主要介紹了C#不可變類型,對于C#程序員深入理解string數(shù)據(jù)類型有很大的幫助,需要的朋友可以參考下
    2014-08-08
  • C#操作RabbitMQ的完整實例

    C#操作RabbitMQ的完整實例

    這篇文章主要為大家詳細(xì)介紹了C#操作RabbitMQ的完整實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08

最新評論