IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity3d C# UGUI实现一个自动循环滚动的列表(ScrollRect)的功能(含工程源码) -> 正文阅读

[游戏开发]Unity3d C# UGUI实现一个自动循环滚动的列表(ScrollRect)的功能(含工程源码)

前言

如题的功能在项目中经常用到,滚动的信息内容,我们用scrollbar的value来控制滚动是可以实现的,不过当value为1时,我们从0继续循环会造成有闪烁的情况而且比较突兀,经过一段时间的研究终于实现了该功能。

效果

分别方向的移动

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实现

自动滚动的思路就是不断的增加某一个方向的偏移值就可以实现,循环滚动时,将最早移出的节点移至滚动队列的最尾端即可,同时计算新的偏移值并同步,让列表看不出抖动,即可实现一直循环滚动,在此过程中将禁用ScrollRect组件,因为ScrollRect组件在节点顺序变化时会造成显示抖动,同时还需根据排序的组件(HorizontalOrVerticalLayoutGroup/GridLayoutGroup)进行间隔的计算。当鼠标悬停时启用ScrollRect组件并暂停滚动,鼠标离开时启用自动滚动并禁用ScrollRect。

搭建UI

如图的搭建一个列表

在这里插入图片描述

定义滚动方向

public enum ScrollDir
{
    BottomToTop = 1,
    TopToBottom = 2,
    LeftToRight = 3,
    RightToLeft = 4
}

定义如上四个方向方便选择设置和分开处理。

初始化数值

        scrollrect = gameObject.GetComponent<ScrollRect>();
        scrolltran = scrollrect.GetComponent<RectTransform>();
        LayoutGroup = scrollrect.content.GetComponent<HorizontalOrVerticalLayoutGroup>();
        GridGroup = scrollrect.content.GetComponent<GridLayoutGroup>();

        et = gameObject.GetComponent<EventTrigger>();
        if (et == null)
            et = gameObject.AddComponent<EventTrigger>();

        //设置滚动间隔
        if (LayoutGroup != null)
            Space = LayoutGroup.spacing;
        else if (GridGroup != null)
        {
            switch (AutoScrollDir)
            {
                case ScrollDir.BottomToTop://由底至顶滚动  向上
                case ScrollDir.TopToBottom://由顶至底滚动  向下
                    Space = GridGroup.spacing.y;
                    break;
                case ScrollDir.LeftToRight://由左至右滚动 →
                case ScrollDir.RightToLeft://由右至左滚动 ←
                    Space = GridGroup.spacing.x;
                    break;
                default:
                    Space = 0;
                    break;
            }

        }

        //设置子节点高度和宽度
        if (LayoutGroup != null && scrollrect.content.childCount > 0)
        {
            ItemWidth = scrollrect.content.GetChild(0).GetComponent<RectTransform>().sizeDelta.x;
            ItemHeight = scrollrect.content.GetChild(0).GetComponent<RectTransform>().sizeDelta.y;
        }
        else if (GridGroup != null)
        {
            ItemWidth = GridGroup.cellSize.x;
            ItemHeight = GridGroup.cellSize.y;
        }
        AddETEvent(et, EventTriggerType.PointerEnter, OnPointerIn);
        AddETEvent(et, EventTriggerType.PointerExit, OnPointerOut);
    

如上代码初始化时候,主要寻找相关组件,排序组件和滚动组件等,同时根据不同组件获取间隔数值,还有排序对象的高宽度,以及事件绑定。这里通过添加EventTrigger组件,并绑定PointerEnter 和 PointerExit来实现鼠标悬停和退出功能。

界面的配置如图:

在这里插入图片描述

自动滚动

 //开始自动滑动
    void DoAutoScroll()
    {
        switch (AutoScrollDir)
        {
            //由底至顶滚动  向上
            case ScrollDir.BottomToTop:
                {
                    if (scrollrect.content.sizeDelta.y > scrolltran.sizeDelta.y + (ItemHeight + Space))
                    {
                        scrollrect.content.anchoredPosition3D += new Vector3(0, step, 0);
                        if (scrollrect.content.anchoredPosition3D.y >= (scrollrect.content.sizeDelta.y - scrolltran.sizeDelta.y) / 2)
                        {
                            if (GridGroup != null && GridGroup.constraintCount > 1)
                            {
                                for (int i = 0; i < GridGroup.constraintCount; i++)
                                    scrollrect.content.GetChild(0).transform.SetAsLastSibling();
                                scrollrect.content.anchoredPosition3D -= new Vector3(0, (ItemHeight + Space), 0);
                            }
                            else
                            {
                                scrollrect.content.GetChild(0).transform.SetAsLastSibling();
                                scrollrect.content.anchoredPosition3D -= new Vector3(0, (ItemHeight + Space), 0);
                            }
                        }
                    }
                }
                break;
            //由顶至底滚动  向下
            case ScrollDir.TopToBottom:
                {
                    if (scrollrect.content.sizeDelta.y > scrolltran.sizeDelta.y + (ItemHeight + Space))
                    {
                        scrollrect.content.anchoredPosition3D -= new Vector3(0, step, 0);
                        if (scrollrect.content.anchoredPosition3D.y <= (scrollrect.content.sizeDelta.y - scrolltran.sizeDelta.y) / 2)
                        {
                            if (GridGroup != null && GridGroup.constraintCount > 1)
                            {
                                for (int i = 0; i < GridGroup.constraintCount; i++)
                                    scrollrect.content.GetChild(scrollrect.content.childCount - 1).transform.SetAsFirstSibling();
                                scrollrect.content.anchoredPosition3D += new Vector3(0, (ItemHeight + Space), 0);
                            }
                            else
                            {
                                scrollrect.content.GetChild(scrollrect.content.childCount - 1).transform.SetAsFirstSibling();
                                scrollrect.content.anchoredPosition3D += new Vector3(0, (ItemHeight + Space), 0);
                            }
                        }
                    }
                }
                break;

            //由左至右滚动 →
            case ScrollDir.LeftToRight:
                {
                    if (scrollrect.content.sizeDelta.x > scrolltran.sizeDelta.x + (ItemWidth + Space))
                    {
                        scrollrect.content.anchoredPosition3D += new Vector3(step, 0, 0);
                        if (scrollrect.content.anchoredPosition3D.x >= -(scrollrect.content.sizeDelta.x - scrolltran.sizeDelta.x) / 2)
                        {
                            if (GridGroup != null && GridGroup.constraintCount > 1)
                            {
                                for (int i = 0; i < GridGroup.constraintCount; i++)
                                    scrollrect.content.GetChild(scrollrect.content.childCount - 1).transform.SetAsFirstSibling();
                                scrollrect.content.anchoredPosition3D -= new Vector3((ItemWidth + Space), 0, 0);
                            }
                            else
                            {
                                scrollrect.content.GetChild(scrollrect.content.childCount - 1).transform.SetAsFirstSibling();
                                scrollrect.content.anchoredPosition3D -= new Vector3((ItemWidth + Space), 0, 0);
                            }
                        }
                    }
                }
                break;
            //由右至左滚动 ←
            case ScrollDir.RightToLeft:
                {
                    if (scrollrect.content.sizeDelta.x > scrolltran.sizeDelta.x + (ItemWidth + Space))
                    {
                        scrollrect.content.anchoredPosition3D -= new Vector3(step, 0, 0);
                        if (scrollrect.content.anchoredPosition3D.x <= -(scrollrect.content.sizeDelta.x - scrolltran.sizeDelta.x) / 2)
                        {
                            if (GridGroup != null && GridGroup.constraintCount > 1)
                            {
                                for (int i = 0; i < GridGroup.constraintCount; i++)
                                    scrollrect.content.GetChild(0).transform.SetAsLastSibling();
                                scrollrect.content.anchoredPosition3D += new Vector3((ItemWidth + Space), 0, 0);
                            }
                            else
                            {
                                scrollrect.content.GetChild(0).transform.SetAsLastSibling();
                                scrollrect.content.anchoredPosition3D += new Vector3((ItemWidth + Space), 0, 0);
                            }
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

这一段就是核心的代码,分别处理了四个方向滚动的过程,大致思路如前面提到的。主要还是Content具备自动滚动的条件:Content的高或者宽超过了视窗+1倍高宽和间隔的长度。开始自动滚动。
移动首个移出节点至队尾的条件:移动的位置已经超过一半。

其中的还有些GridLayoutGroup组件的处理,因为移动节点可能需要同时移动一排 或者一列,具体看脚本。有些特定的设置后面会进行说明。

工程源码

https://download.csdn.net/download/qq_33789001/33215369
如果打不开就是还没审核,最近审核很慢。

注意

这里特别注意的滚动页面的设置,我为了简便快速实现,这里就分成了横竖两个方向的设置做了固定适配。

横向

即从左到右或者从右到左的情况。Content如下设置:
在这里插入图片描述

竖向

即从上到下或者从下到上,Content:
在这里插入图片描述

如果不这样设置可能会有异常。

GridLayoutGroup的StartCorner设置也得是类似的设置,并且多行或者多列时需要固定值:

在这里插入图片描述

这个在移动节点时需要用到,不设置可能异常。也可尝试手动修改代码适配。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-10-19 12:13:25  更:2021-10-19 12:15:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:43:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码