当生成的资源过多,可以采用无限循环列表来防止生成的时候发生卡顿
首先在scrollview加上脚本ScrollRectList
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public enum ListDir {
Horizontal = 1,
Vertical = 2,
}
public class ScrollRectList : MonoBehaviour
{
ScrollRect view;
[HideInInspector]
public RectTransform viewRect;
[HideInInspector]
public RectTransform contentRect;
// 显示的单元列表
List<OneCell> showList;
RectTransform originCell;
float cellWidth, cellHeight, column, topY, leftX, paddingY, paddingX;
int pointDir, listLength;
bool isCreate = false;
Action<RectTransform> createBack;
Action<RectTransform, int> updateBack;
Vector2 lastViewPoint = Vector2.zero;
ListDir curDir = ListDir.Horizontal;
public class OneCell {
public int index;
public RectTransform rect;
}
private void Awake()
{
showList = new List<OneCell>();
view = GetComponent<ScrollRect>();
viewRect = GetComponent<RectTransform>();
// 位置更新监听
view.onValueChanged.AddListener(UpdateView);
contentRect = view.content;
}
void UpdateView(Vector2 viewPoint)
{
if (viewPoint.x < 0 || viewPoint.x > 1 || viewPoint.y > 1 || viewPoint.y < 0)
return;
Vector2 point;
lastViewPoint = viewPoint;
// 隐藏不在视图的单元
List<OneCell> hide = new List<OneCell>();
//长度变小的情况
for (int i = this.listLength; i < this.showList.Count; i++)
{
OneCell temp = this.showList[i];
temp.rect.gameObject.SetActive(false);
hide.Add(temp);
}
for (int i = 0; i < this.showList.Count; i++)
{
OneCell temp = this.showList[i];
if (!CanShow(temp.index, out point))
{
temp.rect.gameObject.SetActive(false);
hide.Add(temp);
}
}
// 显示在视图中的单元
for (int i = 0; i < this.listLength; i++)
{
bool isActive = false;
if (CanShow(i, out point))
{
// 使用显示列表中失活的单元格,激活、更新其数据并设置位置
for (int j = 0; j < this.showList.Count; j++)
{
OneCell temp = this.showList[j];
if (temp.index == i)
{
if (!temp.rect.gameObject.activeSelf)
{
temp.rect.gameObject.SetActive(true);
UpdateCell(temp.rect, i);
temp.rect.SetSiblingIndex(i % this.showList.Count);
}
isActive = true;
break;
}
}
if (!isActive)
{
// 使用隐藏列表中最后一个单元格
if (hide.Count > 0)
{
OneCell temp = hide[hide.Count - 1];
hide.RemoveAt(hide.Count - 1);
temp.rect.gameObject.SetActive(true);
temp.rect.anchoredPosition = point;
temp.rect.name = "cell" + i;
temp.index = i;
UpdateCell(temp.rect, i);
}
// 显示列表没有失活的单元格,隐藏列表没有单元格,则创建一个
else
{
CreateCell(i, point);
}
}
}
}
// 按索引排序显示列表
this.showList.Sort((a, b) =>
{
return a.index.CompareTo(b.index);
});
// 设置单元格的层级顺序
for (int i = 0; i < this.showList.Count; i++)
{
OneCell temp = this.showList[i];
temp.rect.SetSiblingIndex(temp.index);
}
}
public void SetDir(ListDir dir)
{
this.curDir = dir;
}
// 设置单元格宽高、列数和方向
public void SetWH(float cellWidth, float cellHeight, float column = 1, int pointDir = -1) {
this.cellWidth = cellWidth;
this.cellHeight = cellHeight;
this.column = column;
this.pointDir = pointDir;
}
// 设置间距
public void SetPadding(float topY, float paddingY, float leftX, float paddingX) {
this.topY = topY;
this.paddingY = paddingY;
this.leftX = leftX;
this.paddingX = paddingX;
}
public void SetCallBack(Action<RectTransform> createBack, Action<RectTransform, int> updateBack)
{
this.createBack = createBack;
this.updateBack = updateBack;
}
// 设置列表长度
public void SetLength(int length)
{
this.listLength = length;
UpdateSize();
if (isCreate)
{
UpdateView(Vector2.zero);
for (int i = 0; i < showList.Count; i++)
{
OneCell temp = showList[i];
if (temp.rect.gameObject.activeSelf)
UpdateCell(temp.rect, temp.index);
}
}
}
// 设置列表长度并创建单元格
public void SetLength(RectTransform originCell, int length)
{
SetLength(length);
if (isCreate)
return;
isCreate = true;
this.originCell = originCell;
this.originCell.anchoredPosition = IndexToPoint(0);
this.originCell.name = "cell0";
this.originCell.gameObject.SetActive(true);
CreateCell(0, originCell);
Vector2 point;
for (int i = 1; i < length; i++)
{
if (CanShow(i, out point))
{
CreateCell(i, point);
}
else
{
break;
}
}
UpdateView(Vector2.zero);
}
// 创建单元格
public void CreateCell(int index, Vector2 point)
{
RectTransform rect = GameObject.Instantiate(originCell.gameObject).GetComponent<RectTransform>();
rect.anchoredPosition = point;
rect.SetParent(contentRect.transform, false);
rect.name = "cell" + index;
CreateCell(index, rect);
}
// 创建单元格并添加到显示列表
public void CreateCell(int index, RectTransform rect)
{
showList.Add(new OneCell
{
index = index,
rect = rect,
});
this.createBack?.Invoke(rect);
if (this.listLength > index)
UpdateCell(rect, index);
}
public void UpdateCell(RectTransform cell, int index)
{
this.updateBack?.Invoke(cell, index);
}
// 判断单元格是否在视图中
public bool CanShow(int index, out Vector2 point)
{
// 得到索引单元对应的锚点位置
point = IndexToPoint(index);
// content的锚点位置
Vector2 contentPoint = contentRect.anchoredPosition;
if (curDir == ListDir.Horizontal)
{
return point.x + contentPoint.x < viewRect.sizeDelta.x && point.x + this.cellWidth + contentPoint.x > 0;
}
else
{
return pointDir * point.y + pointDir * contentPoint.y < viewRect.sizeDelta.y && pointDir * point.y + this.cellHeight + contentPoint.y * pointDir > 0;
}
}
// 根据索引计算位置,index下标从0开始
public Vector2 IndexToPoint(int index)
{
float x, y;
// 按照左上角锚点来计算
if (curDir == ListDir.Horizontal)
{
x = index * (this.cellWidth + paddingX) + leftX;
y = topY;
}
else
{
x = index % column * (this.cellWidth + paddingX) + leftX;
y = pointDir * Mathf.Floor(index / column) * (this.cellHeight + paddingY) + topY * pointDir;
}
return new Vector2(x, y);
}
// 更新内容大小
public void UpdateSize()
{
//全部按照左上角锚点来计算
if (curDir == ListDir.Horizontal)
{
float w = this.leftX + this.listLength * (this.cellWidth + this.paddingX) - this.paddingX;
contentRect.sizeDelta = new Vector2(w, contentRect.sizeDelta.y);
}
else
{
float h = this.topY + Mathf.Ceil(this.listLength/column) * (this.cellHeight + this.paddingY) - this.paddingY;
contentRect.sizeDelta = new Vector2(contentRect.sizeDelta.x, h);
}
}
// 根据索引获取显示的单元格
public RectTransform GetShowCellByIndex(int index)
{
for (int i = 0; i < showList.Count; i++)
{
if (showList[i].index == index)
return showList[i].rect;
}
return null;
}
// 根据索引跳转
public void jumpByIndex(int index, float offset = 0)
{
Vector2 point = IndexToPoint(index);
view.StopMovement();
view.normalizedPosition = Vector2.zero;
if (curDir == ListDir.Horizontal)
{
contentRect.anchoredPosition = new Vector2(-point.x + offset + leftX, contentRect.anchoredPosition.y);
}
else
{
contentRect.anchoredPosition = new Vector2(contentRect.anchoredPosition.x, -point.y + offset + topY);
}
UpdateView(lastViewPoint);
}
public List<OneCell> GetShowList()
{
return this.showList;
}
}
然后声明 ScrollRectList viewList;
初始化
viewList = ui.m_Reward.GetComponent<ScrollRectList>();
viewList.SetDir(ListDir.Horizontal);
viewList.SetWH(160, 223);
viewList.SetPadding(-25, 0, 50, 35);
viewList.SetCallBack(null, updateCell);
设置长度
viewList.SetLength(view.GetComponent<RectTransform>(), fightDataCompoent.player_buffs.Length);
写更新和创造方法
private void CreateCell(RectTransform cell)
{
/* ThreeBagItem item = cell.GetComponent<ThreeBagItem>();
item.SetCallBack(ShowTips);*/
EquipIcon_View item = cell.GetComponent<EquipIcon_View>();
item.SetCallBack(ShowTips);
}
private void UpdateCell(RectTransform cell, int index)
{
/* int buffId = fightDataCompoent.player_buffs[index];
ThreeBagItem item = cell.GetComponent<ThreeBagItem>();
item.UpdateItem(buffId, _sprites);*/
int buffId = fightDataCompoent.player_buffs[index];
AddAttri addAttri = ConfigManager.Instance.GetTables().TbAddAttri[buffId];
EquipIcon_View item = cell.GetComponent<EquipIcon_View>();
item.UpdateSelf(addAttri);
}