unity无限循环列表

当生成的资源过多,可以采用无限循环列表来防止生成的时候发生卡顿

首先在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);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值