
前言
- 本文介紹一個(gè)UGUI關(guān)于
ScrollRect
的一個(gè)拓展插件:SuperScrollView
。 - 做項(xiàng)目的過(guò)程中,ScrollRect組件 的使用頻率還是挺高的,尤其是在做類(lèi)似背包這種需要大量子對(duì)象的時(shí)候。
- 正常情況下,使用ScrollRect做滑動(dòng)功能時(shí),如果子對(duì)象非常多,在生成時(shí)難免會(huì)卡頓。
- 所以就需要一個(gè)循環(huán)列表,類(lèi)似對(duì)象池的功能,只會(huì)加載顯示頁(yè)面中所需要的,而不是一次性全部加載完成。
【Unity 實(shí)用工具篇】 | UGUI 循環(huán)列表 SuperScrollView,快速上手使用
一、UGUI ScrollRect拓展插件:SuperScrollView
1.1 介紹
UGUI SuperScrollView
基于UGUI ScrollRect提供了易于定制的ScrollView。它是一組C#腳本,可以幫助您創(chuàng)建所需的ScrollView。這是非常強(qiáng)大的和高度優(yōu)化的性能。
在SuperScrollView中主要有三個(gè)組件,并實(shí)現(xiàn)了三種不一樣的循環(huán)列表形式:
- LoopListView2:適用于 橫向/縱向 簡(jiǎn)單排列的列表視圖,類(lèi)似 Vertical Layout Group / Horizontal Layout Group的使用。
- LoopGridView:適用于網(wǎng)格排列,大小相同的列表視圖,類(lèi)似 GridLayout Group 的使用。
- LoopStaggeredGridView:適用于網(wǎng)格排列,但大小不相同的列表視圖,可以實(shí)現(xiàn)列表中錯(cuò)列排序等特殊需求。
下面就來(lái)介紹一下這三種循環(huán)列表的使用方式,快速上手及使用。
1.2 效果展示


1.3 使用說(shuō)明及下載
Unity Asset Store下載地址:https://assetstore./packages/tools/gui/ugui-super-scrollview-86572
CSDN下載地址:SuperScrollView
白嫖地址:VX搜我名字,回復(fù)【素材資源】
使用插件的方式有多種:
- 將下載好的SuperScrollView資源文件直接放到我們的項(xiàng)目Assets文件夾下即可。
- 可以通過(guò)Unity中的 Window -> Package Manager 中導(dǎo)入,選擇添加下載好的插件,或者使用URL直接添加都可以。
二、SuperScrollView 快速上手使用
三種功能的組件在使用時(shí)差別不大,只不過(guò)各個(gè)組件有自己獨(dú)有的幾個(gè)參數(shù)可以選擇,包括添加子對(duì)象,初始生成子對(duì)象的數(shù)量,設(shè)置間距、偏移量和排列類(lèi)型等。

功能比較簡(jiǎn)單,可配置的參數(shù)與Unity常規(guī)的布局組件類(lèi)似,使用起來(lái)很容易上手。
在演示之前先做一個(gè)不使用循環(huán)列表時(shí)的普通示例,在ScrollView下加載1000個(gè)對(duì)象。
簡(jiǎn)單搭建一個(gè)場(chǎng)景,在ScrollView中添加一個(gè)item作為生成的對(duì)象。

Content上面需要掛載對(duì)應(yīng)的布局組件,這里演示掛載一個(gè)垂直布局組件。

Item對(duì)象上面掛載一個(gè)測(cè)試腳本TestItem.cs
using UnityEngine;
using UnityEngine.UI;
public class TestItem : MonoBehaviour
{
public Image ImgIcon;
public Text TxtName;
public void SetData(int _index)
{
TxtName.text = $"測(cè)試:<color=#F55F55>{_index}</color>";
}
}
測(cè)試生成1000個(gè)對(duì)象腳本如下:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoopViewDemo : MonoBehaviour
{
public Button button;
public Transform testContent;
public GameObject testItem;
private void Awake()
{
button.onClick.AddListener(() =>
{
StartTest();
});
}
private void StartTest()
{
for (int i = 0; i < 1000; i++)
{
GameObject go = GameObject.Instantiate(testItem, testContent);
var itemInfo = go.GetComponent<TestItem>();
itemInfo.SetData(i);
}
}
}

此時(shí)運(yùn)行游戲,點(diǎn)擊開(kāi)始按鈕,可以看到1000個(gè)對(duì)象全部被生成。

在游戲中的表現(xiàn)會(huì)出現(xiàn)明顯的卡頓現(xiàn)象,對(duì)象越多越是如此。而且后面的對(duì)象并不會(huì)顯示到玩家可以操作的視圖中,只有不斷往下滑動(dòng)時(shí)才會(huì)顯示,一次性生成白白消耗了性能。
下面看下SuperScrollView的使方法及效果。
2.1 LoopListView2
與前面普通示例一樣正常創(chuàng)建一個(gè)ScrollView以及對(duì)應(yīng)的item,接著在ScrollView上面掛載LoopListView2
腳本,并在LoopListView2上面添加對(duì)應(yīng)的item對(duì)象
(需要循環(huán)生成的游戲?qū)ο?#xff09;。

item對(duì)象需要掛載LoopListViewItem2腳本,如有對(duì)應(yīng)邏輯腳本也可掛載。

這里有兩個(gè)點(diǎn)需要注意
1.不需要在Content上面掛載對(duì)應(yīng)的布局組件了,否則會(huì)出現(xiàn)錯(cuò)亂的效果。
2.ScrollView組件如果需要保留滑動(dòng)條,則不能選擇Auto Hide And Expand Viewport。

使用LoopListView2的代碼如下:
using SuperScrollView;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoopViewDemo : MonoBehaviour
{
public Button button;
public LoopListView2 LoopListView;
private void Awake()
{
button.onClick.AddListener(() =>
{
StartTest();
});
//初始化循環(huán)列表
LoopListView.InitListView(0, refreshListInfo);
}
private void StartTest()
{
//刷新循環(huán)列表
LoopListView.SetListItemCount(1000, true);
}
private LoopListViewItem2 refreshListInfo(LoopListView2 loopListView, int index)
{
if (index < 0 || index > 1000) return null;
LoopListViewItem2 item = loopListView.NewListViewItem("item");
LoopTestItem _itemInfo = item.GetComponent<LoopTestItem>();
_itemInfo.SetData(index);
return item;
}
}
運(yùn)行查看效果:

可以看到使用循環(huán)列表之后1000個(gè)對(duì)象并不會(huì)全部生成,而是最多生成視圖中需要展示的對(duì)象數(shù)量,在滑動(dòng)時(shí)使用對(duì)象池進(jìn)行重復(fù)利用并賦值。
2.2 LoopGridView
LoopGridView與LoopListView2的使用方式基本相同,掛載LoopGridView腳本,添加對(duì)應(yīng)的item并設(shè)置大小和間隔。

同樣的需要在item上面添加LoopGridViewItem腳本。
測(cè)試效果如下,同時(shí)只會(huì)生成部分對(duì)象,不會(huì)全部生成。

使用LoopGridView的代碼如下:
using SuperScrollView;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoopViewDemo : MonoBehaviour
{
public Button button;
public LoopGridView LoopGridView;
private void Awake()
{
button.onClick.AddListener(() =>
{
StartTest();
});
//初始化循環(huán)列表
LoopGridView.InitGridView(0, refreshListInfo);
}
private void StartTest()
{
//刷新循環(huán)列表
LoopGridView.SetListItemCount(1000, true);
}
private LoopGridViewItem refreshListInfo(LoopGridView loopListView, int arg2, int arg3, int arg4)
{
if (arg2 < 0 || arg2 > 1000) return null;
LoopGridViewItem item = loopListView.NewListViewItem("item");
LoopTestItem _itemInfo = item.GetComponent<LoopTestItem>();
_itemInfo.SetData(arg2);
return item;
}
}
2.3 LoopStaggeredGridView
LoopStaggeredGridView的使用方法與前兩個(gè)也是基本相同,只不過(guò)在腳本中可以設(shè)置對(duì)象之間的間隔。
在LoopGridView中,每個(gè)對(duì)象之間的間隔都是相同的,而使用LoopStaggeredGridView時(shí)可以自由設(shè)置每行/列的間隔大小及行列數(shù),下面看下使用方法。
與前面兩種類(lèi)似,還是一樣的腳本掛載方式。

測(cè)試效果如下:

使用LoopStaggeredGridView的代碼如下:
using SuperScrollView;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoopViewDemo : MonoBehaviour
{
public Button button;
public Button button2;
public LoopStaggeredGridView loopStaggeredGridView;
private void Awake()
{
button.onClick.AddListener(() =>
{
StartTest();
});
button2.onClick.AddListener(() =>
{
UpdateTest();
});
GridViewLayoutParam layoutParam = new GridViewLayoutParam()
{ mColumnOrRowCount = 3, mItemWidthOrHeight = 1, mCustomColumnOrRowOffsetArray = new float[] { 0, 222, 666 } };
loopStaggeredGridView.InitListView(0, layoutParam, refreshStaggeredListInfo);
}
private void StartTest()
{
//刷新循環(huán)列表
loopStaggeredGridView.SetListItemCount(1000, true);
}
private void UpdateTest()
{
GridViewLayoutParam layoutParam = new GridViewLayoutParam()
{ mColumnOrRowCount = 4, mItemWidthOrHeight = 1, mCustomColumnOrRowOffsetArray = new float[] { 0, 444, 666,1111 } };
loopStaggeredGridView.ResetGridViewLayoutParam(1000, layoutParam);
}
private LoopStaggeredGridViewItem refreshStaggeredListInfo(LoopStaggeredGridView loopListView, int index)
{
if (index < 0 || index > 1000) return null;
LoopStaggeredGridViewItem item = loopListView.NewListViewItem("item");
LoopTestItem _itemInfo = item.GetComponent<LoopTestItem>();
_itemInfo.SetData(index);
return item;
}
}
與前兩種不同的是,在刷新列表時(shí)需要多傳入一個(gè)參數(shù)GridViewLayoutParam,用于控制行/列數(shù)及不同行/列之間的間隔大小。
一般情況下用到這種組件的機(jī)會(huì)不多,了解相關(guān)功能參考下即可。
三、其他案例
SuperScrollView 還提供了很多種不同的展示效果,具體可以在官方案例查看,這里演示幾種作為參考。


3.1 滾動(dòng)時(shí)大小變化

完整代碼如下:
using SuperScrollView;
using UnityEngine;
public class LoopListViewExample : MonoBehaviour
{
[SerializeField] private LoopListView2 m_view = null;
private void Start()
{
m_view.InitListView(100, OnUpdate);
}
private void LateUpdate()
{
m_view.UpdateAllShownItemSnapData();
int count = m_view.ShownItemCount;
for (int i = 0; i < count; ++i)
{
var itemObj = m_view.GetShownItemByIndex(i);
var itemUI = itemObj.GetComponent<LoopTestItem>();
var amount = 1 - Mathf.Abs(itemObj.DistanceWithViewPortSnapCenter) / 720f;
var scale = Mathf.Clamp(amount, 0.4f, 1);
itemUI.SetScale(scale);
}
}
private LoopListViewItem2 OnUpdate(LoopListView2 view, int index)
{
if (index < 0 || index > 100) return null;
var itemObj = view.NewListViewItem("item");
var itemUI = itemObj.GetComponent<LoopTestItem>();
itemUI.SetData(index);
return itemObj;
}
}
using UnityEngine;
using UnityEngine.UI;
public class LoopTestItem : MonoBehaviour
{
public Transform RootTrans;
public Image ImgIcon;
public Text TxtName;
public void SetData(int _index)
{
TxtName.text = $"測(cè)試:<color=#F55F55>{_index}</color>";
}
public void SetScale(float scale)
{
RootTrans.GetComponent<CanvasGroup>().alpha = scale;
RootTrans.transform.localScale = new Vector3(scale, scale, 1);
}
}
需要在子對(duì)象掛載的腳本中添加一個(gè)SetScale方法用來(lái)控制大小及各種變化。
3.2 多個(gè)不同類(lèi)型子對(duì)象
SuperScrollView 還支持多個(gè)不同類(lèi)型的子對(duì)象根據(jù)具體需求同時(shí)生成,用來(lái)滿足再循環(huán)列表中有不同游戲?qū)ο蟮男枨?#xff0c;下面拿LoopListView2做演示效果
與正常使用LoopListView2類(lèi)似,在ScrollView上面掛載LoopListView2腳本,并在LoopListView2上面添加對(duì)應(yīng)的item對(duì)象,只不過(guò)可以根據(jù)需求添加多個(gè)子對(duì)象。
具體操作如下圖所示:

然后在使用時(shí),可以根據(jù)自己所需的條件去指定生成不同的子對(duì)象,比如下面示例根據(jù)奇偶生成不同類(lèi)型的子對(duì)象。
代碼示例如下:
using SuperScrollView;
using UnityEngine;
public class LoopListViewExample : MonoBehaviour
{
[SerializeField] private LoopListView2 m_view = null;
private void Start()
{
m_view.InitListView(100, OnUpdate);
}
private LoopListViewItem2 OnUpdate(LoopListView2 view, int index)
{
if (index < 0 || index > 100) return null;
var itemType = view.NewListViewItem("itemType1");
if (index % 2 == 0)
{
itemType = view.NewListViewItem("itemType1");
}
else
{
itemType = view.NewListViewItem("itemType2");
}
var itemUI = itemType.GetComponent<LoopTestItem>();
itemUI.SetData(index);
return itemType;
}
}
效果如下:

總結(jié)
- 本文演示了UGUI 中循環(huán)列表 SuperScrollView的使用方法及幾個(gè)使用示例。
- 該組件已經(jīng)在很多項(xiàng)目中驗(yàn)證過(guò),使用起來(lái)沒(méi)有什么問(wèn)題,所以可以放心食用。
-
🎬 博客主頁(yè):https://xiaoy.blog.csdn.net
-
🎥 本文由 呆呆敲代碼的小Y 原創(chuàng) 🙉
-
🎄 學(xué)習(xí)專(zhuān)欄推薦:Unity系統(tǒng)學(xué)習(xí)專(zhuān)欄
-
🌲 游戲制作專(zhuān)欄推薦:游戲制作
-
🌲Unity實(shí)戰(zhàn)100例專(zhuān)欄推薦:Unity 實(shí)戰(zhàn)100例 教程
-
🏅 歡迎點(diǎn)贊 👍 收藏 ?留言 📝 如有錯(cuò)誤敬請(qǐng)指正!
-
📆 未來(lái)很長(zhǎng),值得我們?nèi)Ρ几案篮玫纳?
-
------------------??分割線??-------------------------




資料白嫖,技術(shù)互助
學(xué)習(xí)路線指引(點(diǎn)擊解鎖) | 知識(shí)定位 | 人群定位 |
---|
🧡 Unity系統(tǒng)學(xué)習(xí)專(zhuān)欄 🧡 | 入門(mén)級(jí) | 本專(zhuān)欄從Unity入門(mén)開(kāi)始學(xué)習(xí),快速達(dá)到Unity的入門(mén)水平 |
💛 Unity實(shí)戰(zhàn)類(lèi)項(xiàng)目 💛 | 進(jìn)階級(jí) | 計(jì)劃制作Unity的 100個(gè)實(shí)戰(zhàn)案例!助你進(jìn)入U(xiǎn)nity世界,爭(zhēng)取做最全的Unity原創(chuàng)博客大全。 |
?? 游戲制作專(zhuān)欄 ?? | 難度偏高 | 分享學(xué)習(xí)一些Unity成品的游戲Demo和其他語(yǔ)言的小游戲! |
💚 游戲愛(ài)好者萬(wàn)人社區(qū)💚 | 互助/吹水 | 數(shù)萬(wàn)人游戲愛(ài)好者社區(qū),聊天互助,白嫖獎(jiǎng)品 |
💙 Unity100個(gè)實(shí)用技能💙 | Unity查漏補(bǔ)缺 | 針對(duì)一些Unity中經(jīng)常用到的一些小知識(shí)和技能進(jìn)行學(xué)習(xí)介紹,核心目的就是讓我們能夠快速學(xué)習(xí)Unity的知識(shí)以達(dá)到查漏補(bǔ)缺 |