文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Unity ScrollView如何实现无限滑动效果

2023-06-20 18:14

关注

小编给大家分享一下Unity ScrollView如何实现无限滑动效果,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

一、效果演示

Unity ScrollView如何实现无限滑动效果

二、前言

当邮件中有1000封邮件,商店列表中有1000个物体,如果直接实例化1000条数据显示则会大大增加DrawCall,而大量不可见的数据被Mask组件排除在可视范围之外,但他们依然存在,这时就需要考虑通过一个无限滑动的ScrollView来优化渲染性能

三、实现思路

通过头下标和尾下标记录当前实例化数据的最大最小索引,之后用Content的锚点位置与当头下标的锚点位置进行比较判断滑动的方向以及是否超出滑动范围,如果正方向滑动超出范围则将第一个元素移动到最后一个,如果反方向滑动超出范围则将最后一个元素移动到第一个,这样场景中始终存在5个实例化的元素,依次改变元素的位置和显示即可

四、使用说明

——此功能脚本是对ScrollRect的扩展,所以必须添加UGUI提供的基础Scroll View
——Content上必须添加GridLayoutGroup组件,通过GridLayoutGroup组件设计布局,(我在代码中对startCorner、startAxis、childAlignment和constraintCount进行了限制,不需要对其设置)
——不能添加Content Size Fitter组件
——先调用SetTotalCount方法设置总的数据数量再调用Init方法进行初始化
——根据需求修改SetShow方法体
——只适用于单向滑动的情况,不能满足竖直和水平同时滑动的需求,因为大多数无限滑动列表的使用场景都是单向的

五、完整代码

将InfiniteScrollView脚本挂载到ScrollView上

using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;using System.Linq; /// <summary>/// 无限滑动列表/// </summary>public class InfiniteScrollView : MonoBehaviour{    private ScrollRect scrollRect;//滑动框组件    private RectTransform content;//滑动框的Content    private GridLayoutGroup layout;//布局组件     [Header("滑动类型")]    public ScrollType scrollType;    [Header("固定的Item数量")]    public int fixedCount;    [Header("Item的预制体")]    public GameObject itemPrefab;     private int totalCount;//总的数据数量    private List<RectTransform> dataList = new List<RectTransform>();//数据实体列表    private int headIndex;//头下标    private int tailIndex;//尾下标    private Vector2 firstItemAnchoredPos;//第一个Item的锚点坐标     #region Init     /// <summary>    /// 实例化Item    /// </summary>    private void InitItem()    {        for (int i = 0; i < fixedCount; i++)        {            GameObject tempItem = Instantiate(itemPrefab, content);            dataList.Add(tempItem.GetComponent<RectTransform>());            SetShow(tempItem.GetComponent<RectTransform>(), i);        }    }     /// <summary>    /// 设置Content大小    /// </summary>    private void SetContentSize()    {        content.sizeDelta = new Vector2            (                layout.padding.left + layout.padding.right + totalCount * (layout.cellSize.x + layout.spacing.x) - layout.spacing.x - content.rect.width,                layout.padding.top + layout.padding.bottom + totalCount * (layout.cellSize.y + layout.spacing.y) - layout.spacing.y            );    }     /// <summary>    /// 设置布局    /// </summary>    private void SetLayout()    {        layout.startCorner = GridLayoutGroup.Corner.UpperLeft;        layout.startAxis = GridLayoutGroup.Axis.Horizontal;        layout.childAlignment = TextAnchor.UpperLeft;        layout.constraintCount = 1;        if (scrollType == ScrollType.Horizontal)        {            scrollRect.horizontal = true;            scrollRect.vertical = false;            layout.constraint = GridLayoutGroup.Constraint.FixedRowCount;        }        else if (scrollType == ScrollType.Vertical)        {            scrollRect.horizontal = false;            scrollRect.vertical = true;            layout.constraint = GridLayoutGroup.Constraint.FixedColumnCount;        }    }     /// <summary>    /// 得到第一个数据的锚点位置    /// </summary>    private void GetFirstItemAnchoredPos()    {        firstItemAnchoredPos = new Vector2            (                layout.padding.left + layout.cellSize.x / 2,                -layout.padding.top - layout.cellSize.y / 2            );    }     #endregion     #region Main     /// <summary>    /// 滑动中    /// </summary>    private void OnScroll(Vector2 v)    {        if (dataList.Count == 0)        {            Debug.LogWarning("先调用SetTotalCount方法设置数据总数量再调用Init方法进行初始化");            return;        }         if (scrollType == ScrollType.Vertical)        {            //向上滑            while (content.anchoredPosition.y >= layout.padding.top + (headIndex + 1) * (layout.cellSize.y + layout.spacing.y)            && tailIndex != totalCount - 1)            {                //将数据列表中的第一个元素移动到最后一个                RectTransform item = dataList[0];                dataList.Remove(item);                dataList.Add(item);                 //设置位置                SetPos(item, tailIndex + 1);                //设置显示                SetShow(item, tailIndex + 1);                 headIndex++;                tailIndex++;            }            //向下滑            while (content.anchoredPosition.y <= layout.padding.top + headIndex * (layout.cellSize.y + layout.spacing.y)                && headIndex != 0)            {                //将数据列表中的最后一个元素移动到第一个                RectTransform item = dataList.Last();                dataList.Remove(item);                dataList.Insert(0, item);                 //设置位置                SetPos(item, headIndex - 1);                //设置显示                SetShow(item, headIndex - 1);                 headIndex--;                tailIndex--;            }        }        else if (scrollType == ScrollType.Horizontal)        {            //向左滑            while (content.anchoredPosition.x <= -layout.padding.left - (headIndex + 1) * (layout.cellSize.x + layout.spacing.x)            && tailIndex != totalCount - 1)            {                //将数据列表中的第一个元素移动到最后一个                RectTransform item = dataList[0];                dataList.Remove(item);                dataList.Add(item);                 //设置位置                SetPos(item, tailIndex + 1);                //设置显示                SetShow(item, tailIndex + 1);                 headIndex++;                tailIndex++;            }            //向右滑            while (content.anchoredPosition.x >= -layout.padding.left - headIndex * (layout.cellSize.x + layout.spacing.x)            && headIndex != 0)            {                //将数据列表中的最后一个元素移动到第一个                RectTransform item = dataList.Last();                dataList.Remove(item);                dataList.Insert(0, item);                 //设置位置                SetPos(item, headIndex - 1);                //设置显示                SetShow(item, headIndex - 1);                 headIndex--;                tailIndex--;            }        }    }     #endregion     #region Tool     /// <summary>    /// 设置位置    /// </summary>    private void SetPos(RectTransform trans, int index)    {        if (scrollType == ScrollType.Horizontal)        {            trans.anchoredPosition = new Vector2            (                index == 0 ? layout.padding.left + firstItemAnchoredPos.x :                layout.padding.left + firstItemAnchoredPos.x + index * (layout.cellSize.x + layout.spacing.x),                firstItemAnchoredPos.y            );        }        else if (scrollType == ScrollType.Vertical)        {            trans.anchoredPosition = new Vector2            (                firstItemAnchoredPos.x,                index == 0 ? -layout.padding.top + firstItemAnchoredPos.y :                -layout.padding.top + firstItemAnchoredPos.y - index * (layout.cellSize.y + layout.spacing.y)            );        }    }     #endregion     #region 外部调用     /// <summary>    /// 初始化    /// </summary>    public void Init()    {        scrollRect = GetComponent<ScrollRect>();        content = scrollRect.content;        layout = content.GetComponent<GridLayoutGroup>();        scrollRect.onValueChanged.AddListener((Vector2 v) => OnScroll(v));         //设置布局        SetLayout();         //设置头下标和尾下标        headIndex = 0;        tailIndex = fixedCount - 1;         //设置Content大小        SetContentSize();         //实例化Item        InitItem();         //得到第一个Item的锚点位置        GetFirstItemAnchoredPos();    }     /// <summary>    /// 设置显示    /// </summary>    public void SetShow(RectTransform trans, int index)    {        //=====根据需求进行编写        trans.GetComponentInChildren<Text>().text = index.ToString();        trans.name = index.ToString();    }     /// <summary>    /// 设置总的数据数量    /// </summary>    public void SetTotalCount(int count)    {        totalCount = count;    }     /// <summary>    /// 销毁所有的元素    /// </summary>    public void DestoryAll()    {        for (int i = dataList.Count - 1; i >= 0; i--)        {            DestroyImmediate(dataList[i].gameObject);        }        dataList.Clear();    }     #endregion} /// <summary>/// 滑动类型/// </summary>public enum ScrollType{    Horizontal,//竖直滑动    Vertical,//水平滑动}

以上是“Unity ScrollView如何实现无限滑动效果”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯