【unity小技巧】实现无限滚动视图和类似CSGO的开箱抽奖功能及Content Size Fitter组件的使用介绍

news2024/12/30 8:57:50

文章目录

  • 一篇一句
  • 前言
  • 素材
  • 一、无限滚动视图
    • 1. 绘制视图
    • 2. Content Size Fitter是布局控件
      • (1)在文本框中使用
      • (2)控制Scroll View(Scroll Rect组件)控件下Content的大小
    • 3. 控制视图无限滚动
    • 4. 向右拉无限滚动
    • 5. 修复滚动视图一卡一卡的问题
  • 二、滚动选中视图
    • 1. 和前面差不多 添加滚动视图
    • 2. 挂载代码并配置参数
  • 源码
  • 完结

一篇一句

我们总喜欢拿顺其自然,敷衍人生道路上的荆棘坎坷,却很少承认,真正的顺其自然,其实是竭尽所能之后的不强求,而非两手一摊的不作为。 ——瑞卡斯

前言

先来看看最终实现效果

无限滚动视图
在这里插入图片描述
滚动选中视图
在这里插入图片描述

素材

链接:https://pan.baidu.com/s/159PuQjxYA0jdSLQ6y65mYw?pwd=qy5q
提取码:qy5q

一、无限滚动视图

1. 绘制视图

新增滚动视图,并禁止垂直滚动
在这里插入图片描述

添加布局组件和内容大小控制容器(设置为水平首选)
为什么使用Content Size Fitter是布局控件下面会介绍
在这里插入图片描述
添加遮罩组件Rect Mask 2D
在这里插入图片描述
添加字体
在这里插入图片描述
最终效果
在这里插入图片描述

2. Content Size Fitter是布局控件

这里我觉得有必要解释一下Content Size Fitter是布局控件的作用

(1)在文本框中使用

在文本框中添加这个Content Size Fitter组件,并设置为Preferred Size之后
文本框就会跟随文字的大小自由变化了,也是一个小技巧,但是就不可以再自定义控制文本框的大小了
在这里插入图片描述

(2)控制Scroll View(Scroll Rect组件)控件下Content的大小

  • 在使用Scroll View组件的时候,一般会设置Content的大小来调节现实的内容
  • 如果Content下的东西太多,就会拖不到最后面的模块了,所以这个时候给Content添加一个Content Size Fitter组件,将Vertical Fit的值设置为Preferred Size,那我们就不需要关心Content的Heigh高度了,这个时候就不怕子物体的多少了,都会正常显示出来。

演示一下
未使用Content Size Fitter组件的情况:
在这里插入图片描述
使用Content Size Fitter组件的情况:
在这里插入图片描述
可以看到未添加Content Size Fitter组件时,因为Content的大小我并没有手动调节到一个合适的大小,导致下面的拖不到
即使鼠标拖过去了,松开的时候也会返回到原来的位置

所以这个时候添加Content Size Fitter组件后,我们就可以达到一个理想的效果了
不用在考虑Content的大小调节了!

3. 控制视图无限滚动

using UnityEngine;
using UnityEngine.UI;

public class InfiniteScroll : MonoBehaviour
{
    public ScrollRect scrollRect;  // 滚动视图组件,用于控制滚动行为
    public RectTransform viewPortTransform;  // 可视区域的RectTransform组件,用于获取可视区域的大小
    public RectTransform contentPanelTransform;  // 内容面板的RectTransform组件,用于放置项的容器
    public HorizontalLayoutGroup HLG;  // 水平布局组件,用于计算项之间的间距和对齐方式
    public RectTransform[] ItemList;  // 项的列表,包含了所有可能的项

    void Start()
    {
        // 按照空白间距(spacing)和项的宽度(width),计算可视区域所需的项数
        int ItemsToAdd = Mathf.CeilToInt(viewPortTransform.rect.width / (ItemList[0].rect.width + HLG.spacing));

        Debug.Log(ItemsToAdd);

        // 根据上面计算出来的项数,创建轮播的初始项
        for (int i = 0; i < ItemsToAdd; i++)
        {
            // 创建首批项并放置在内容面板的末尾
            RectTransform RT = Instantiate(ItemList[i % ItemList.Length], contentPanelTransform);
            //将新创建的项放置在内容面板的末尾,确保它们按顺序排列
            RT.SetAsLastSibling();
        }

        // 创建轮播的补位项,确保用户向左或向右滚动时都有相应的项可供显示
        for (int i = 0; i < ItemsToAdd; i++)
        {
            // 计算下一批项在ItemList中的索引
            int num = ItemList.Length - i - 1;

            while (num < 0)
            {
                // 对索引进行循环处理,确保不超过ItemList的长度
                num += ItemList.Length;
            }
            // 创建更多的项并放置在内容面板的开头
            RectTransform RT = Instantiate(ItemList[num], contentPanelTransform);
            //将新创建的项放置在内容面板的开头,确保它们按顺序排列
            RT.SetAsFirstSibling();
        }

		// 计算并设置内容面板的初始位置,使得第一批轮播项的左侧与可视区域的左侧对齐
        contentPanelTransform.localPosition = new Vector3(
            (0 - (ItemList[0].rect.width + HLG.spacing) * ItemsToAdd),  // 需要向左偏移的距离
            contentPanelTransform.localPosition.y,  // 不需要上下偏移
            contentPanelTransform.localPosition.z  // 不需要前后偏移
        );
    }
}

挂载脚本,配置好参数
在这里插入图片描述

效果
在这里插入图片描述

4. 向右拉无限滚动

void Update()
{
    // 如果内容面板偏移到可视区域左侧之外,则将其向右偏移一个完整的项的宽度
    if (contentPanelTransform.localPosition.x > 0)
    {
        // 强制更新画布,确保UI显示正确
        Canvas.ForceUpdateCanvases();
        contentPanelTransform.localPosition -= new Vector3(ItemList.Length * (ItemList[0].rect.width + HLG.spacing), 0, 0);
    }
    // 如果内容面板偏移到可视区域右侧之外,则将其向左偏移一个完整的项的宽度
    if (contentPanelTransform.localPosition.x < 0 - (ItemList.Length * (ItemList[0].rect.width + HLG.spacing)))
    {
        // 强制更新画布,确保UI显示正确
        Canvas.ForceUpdateCanvases();
        contentPanelTransform.localPosition += new Vector3(ItemList.Length * (ItemList[0].rect.width + HLG.spacing), 0, 0);
    }
}

效果
在这里插入图片描述

5. 修复滚动视图一卡一卡的问题

内容面板的速度会出现奇怪的行为,出现这种行为是因为当我们更改内容面板的位置时,它会影响速度计算,为了解决这个问题,当我们重置内容面板的位置时,我们需要忽略帧上的这些计算

修改代码

Vector2 Oldvelocity;// 上一帧的滚动速度
bool isUpdated;// 是否需要更新滚动速度

void Start()
{
    isUpdated = false;
    Oldvelocity = Vector2.zero;
    
    //。。。
}
void Update()
{
    // 如果需要更新滚动速度,则将当前速度设置为上一帧的速度
    if(isUpdated){
        isUpdated = false;
        scrollRect.velocity = Oldvelocity;
    }

    if (contentPanelTransform.localPosition.x > 0)
    {
        // 。。。

        // 更新滚动速度
        Oldvelocity = scrollRect.velocity;
        isUpdated = true;
    }
    // 如果内容面板偏移到可视区域右侧之外,则将其向左偏移一个完整的项的宽度
    if (contentPanelTransform.localPosition.x < 0 - (ItemList.Length * (ItemList[0].rect.width + HLG.spacing)))
    {
        //。。。
        
        // 更新滚动速度
        Oldvelocity = scrollRect.velocity;
        isUpdated = true;
    }
}

效果,滚动就很平滑了
在这里插入图片描述

二、滚动选中视图

类似CSGO的开箱抽奖功能

1. 和前面差不多 添加滚动视图

在这里插入图片描述
效果
在这里插入图片描述

添加代码控制

x取整获得物品序号;ScrollRect.velocity判断滚动状态;Mathf.MoveTowards做平滑吸附;

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class SnapToItem : MonoBehaviour
{
    public ScrollRect scrollRect;           // 滚动视图组件
    public RectTransform contentPanel;      // 内容面板组件
    public RectTransform sampleListItem;    // 样本列表项组件
    public HorizontalLayoutGroup HLG;       // 水平布局组件
    public TMP_Text NameLabel;              // 显示当前选中项的标签
    public string[] ItemNames;              // 列表项的名称数组

    bool isSnapped;                         // 是否已经对齐到了一个物品
    public float snapForce;                 // 对齐时的强度
    float snapSpeed;                        // 对齐时的速度

    void Start()
    {
        isSnapped = false;
    }

    void Update()
    {
        // 当前选中项的索引
        int currentItem = Mathf.RoundToInt((0 - contentPanel.localPosition.x) / (sampleListItem.rect.width + HLG.spacing));
        Debug.Log(currentItem);

        // 如果滚动速度小于200且没有对齐到一个物品,则进行对齐操作
        if (scrollRect.velocity.magnitude < 200 && !isSnapped)
        {
            scrollRect.velocity = Vector2.zero;
            snapSpeed += snapForce * Time.deltaTime;
            contentPanel.localPosition = new Vector3(
                Mathf.MoveTowards(contentPanel.localPosition.x, 0 - (currentItem * (sampleListItem.rect.width + HLG.spacing)), snapSpeed),
                contentPanel.localPosition.y,
                contentPanel.localPosition.z);
            
            // 更新当前选中项的标签
            if (currentItem >= 0 && currentItem < ItemNames.Length)
            {
                NameLabel.text = ItemNames[currentItem];
            }
            else
            {
                NameLabel.text = "_____";
            }

            // 如果已经对齐到了一个物品,则停止对齐
            if (contentPanel.localPosition.x == 0 - (currentItem * (sampleListItem.rect.width + HLG.spacing)))
            {
                isSnapped = true;
            }
        }

        // 如果滚动速度大于200,则重置对齐状态
        if(scrollRect.velocity.magnitude > 200)
        {
            NameLabel.text = "_____";
            isSnapped = false;
            snapSpeed = 0;
        }
    }
}

2. 挂载代码并配置参数

在这里插入图片描述
效果
在这里插入图片描述

源码

为了防止大家变懒,源码就不提供了,大家直接可以照着文章思路进行学习

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。点赞越多,更新越快哦!当然,如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

julia笔记:字符和字符串

1 字符 Char类型的值代表单个字符 ca #a: ASCII/Unicode U0061 (category Ll: Letter, lowercase)typeof(c) #Char 将 Char 转换为其对应的整数值&#xff0c;即 Unicode 代码 cInt(c) c #97typeof(c) #Int64 将一个整数值&#xff08;Unicaode&#xff09;转回 Char Cha…

杂谈:DC对Verilog和SystemVerilog语言的支持

DC对Verilog和SystemVerilog语言的支持 设计语言用哪种&#xff1f;Design Compiler对二者的支持简单的fsm电路测试测试结果对比写在最后 设计语言用哪种&#xff1f; 直接抛出结论&#xff1a;先有电路&#xff0c;后为描述。设计端而言&#xff0c;没有语言的高低好坏&#…

IMX6ULL板开发——第一个应用程序

实现第一个应用程序&#xff1a;在IMX6ULL开发板上运行程序hello.c #include <stdio.h>/* 执行命令: ./hello weidongshan* argc 2* argv[0] ./hello* argv[1] weidongshan*/int main(int argc, char **argv) {if (argc > 2)printf("Hello, %s!\n", arg…

ASRPRO语音识别模块

ASRPRO语音识别模块 SOFT IIC 与PCA9685模块通信 pca9685 iic通信 地址位 ADDR<<1|0 左移一位 #define I2C_WRITE 0 #define I2C_READ 1 否则通信地址错误 asrpro 通过UART与电脑连接&#xff0c;可以进行简单的交互 将STM32作为接口扩展&#xff0c;通过SPI或I…

【RNA folding】RNA折叠算法与生物物理约束

文章目录 RNA折叠RNA folding representation1 DP for simple folds1.1 Nussinov Algorithm objective1.2 energy constraints1.3 The key idea of the algorithm 2 DP for stacking and complex foldsStochastic context free grammars 来自Manolis Kellis教授&#xff08;MIT…

JavaSE入门---掌握抽象类和接口

文章目录 抽象类什么是抽象类&#xff1f;抽象类语法抽象类特性 接口什么是接口&#xff1f;接口语法接口使用接口特性实现多个接口接口间的继承 抽象类 VS 接口Java中的 Clonable 接口Java中的 Object 类 抽象类 什么是抽象类&#xff1f; 在面向对象的概念中&#xff0c;所…

Linux编译器-gcc/g++使用函数库

【Linux】系列文章目录 【Linux】基础常见指令&#xff1a;http://t.csdn.cn/hwLPb 【Linux】基本权限&#xff1a;http://t.csdn.cn/faFZg 【Linux】软件包管理器yum与环境开发工具vim&#xff1a;http://t.csdn.cn/LEqkm 目录 【Linux】系列文章目录 前言 一、gcc选项总…

【C语言】malloc()函数详解(动态内存开辟函数)

一.malloc()函数简介 我们先来看一下cplusplus.com - The C Resources Network网站上malloc()函数的基本信息&#xff1a; 1.函数功能 可以看到,malloc()函数的功能是:向内存申请一块连续可用的空间,并返回指向块开头的指针. 2.函数参数 该函数有1个参数,是: void* malloc (…

关于iterm2的美化

iterm2 美化 笔者公司最近给发了一个新 M1 mac pro&#xff0c;所以一些软件需要重新安装。其中比较麻烦就是iterm2的一个美化工程 &#xff0c; 由于每次安装的效果都不尽相同所以这次写一个博客来记录一下 安装的过程 。 全程高能开始&#xff1a; 使用brew 来安装 iterm2 …

26. 通过 cilium pwru了解网络包的来龙去脉

pwru是一种基于eBPF的工具,可跟踪Linux内核中的网络数据包,并具有先进的过滤功能。它允许对内核状态进行细粒度检查,以便通过调试网络连接问题来解决传统工具(如iptables TRACE或tcpdump)难以解决甚至无法解决的问题。在本文中,我将介绍pwru如何在不必事先了解所有内容的…

C++ 模板类编译前需要实例化

在复习list容器的模拟实现&#xff0c;遇到了模板未实例化导致代码报错的问题&#xff0c;list的模拟实现可以看下面这篇文章&#xff0c;这里就不多赘述了&#xff0c;直接切入正题。Clist模拟http://t.csdnimg.cn/N6BGh现在的情况是我们已经模拟实现了list类&#xff0c;想在…

1024 漏洞综合项目演示(第十七课)

1024 漏洞综合项目演示(第十七课) 一 渗透流程 前期交互&#xff08;Reconnaissance&#xff09;&#xff1a;这是一个信息收集的阶段&#xff0c;黑客或攻击者会收集目标系统或网络的信息&#xff0c;例如域名、IP地址、子网结构、网络拓扑等。 信息收集&#xff08;Informa…

开源博客项目Blog .NET Core源码学习(4:生成验证码)

开源博客项目Blog中的后台管理登录界面中支持输入验证码&#xff08;如下图所示&#xff09;&#xff0c;本文学习并记录项目中验证码的生成及调用方式。   博客项目中调用VerifyCode类生成验证码&#xff0c;该类位于App.Framwork项目中&#xff0c;命名空间为App.Framwork…

[Docker]一.Docker 简介与安装

一、Docker简介与为什么要用 Docker 1.1、Docker 介绍 Docker 是一个跨平台的开源的 应用容器引擎 &#xff0c;诞生于 2013 年初&#xff0c;基于 Go语言 并遵从 Apache2.0 协议开源, Docker 可以把它理解成虚拟机&#xff0c;但是 Docker 和传统虚拟化方式 有所不同 …

玩转视频剪辑全攻略:批量添加上自定义封面的技巧

在进行视频编辑的过程中&#xff0c;我们经常需要为视频添加引人入胜的封面&#xff0c;以吸引观众的注意力。以下是一份详细的全攻略&#xff0c;指导你如何批量添加自定义的视频封面。 首先&#xff0c;你需要在浏览器中搜索并下载“固乔智剪软件”&#xff0c;这是一款功能强…

精通Linux系列第三章:文件系统管理与权限设置(含目录结构思维导图)

文章目录 一、前言二、文件系统概述2.1 文件系统的定义2.2 常见的Linux文件系统2.3 查看当前Linux系统所使用的文件系统2.4 怎么使用特定的文件系统2.5 文件系统的层次结构 三、文件和目录管理3.1 文件和目录的基本概念3.2 创建文件和目录3.3 查看文件和目录信息3.4 复制、移动…

codeforces (C++ Simple Design)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、难点在于读题&#xff0c;输入两个数x&#xff0c;k&#xff0c;从x开始递增寻找最小可整除k的数。 代码&#xff1a; #include<iostream> using namespace std; int main() {int x, k;int n;cin >> n;…

使用 OpenGL 渲染会旋转 会变色的三角形(LearnOpenGL P3)

文章目录 前言代码 前言 本文参考文献&#xff0c;侵删&#xff01;LearnOpenGL - 你好&#xff0c;三角形 本文将假设您完成了 OpenGL 的配置&#xff0c;并且使用 VAO、VBO 渲染图形 由于时间问题&#xff0c;代码的详细讲解将在几日内给出~ 代码 #include <glad/glad…

UML类图中各箭头表示总结

UML类图中各箭头表示总结 1、泛化2、实现3、依赖4、关联5、聚合6、组合 在UML类图中&#xff0c;箭头关系是用来表示类之间的关系的。箭头关系的种类有以下几种&#xff1a; 1、泛化 泛化&#xff1a;表示类之间的继承关系。箭头从子类指向父类。箭头&#xff1a;实线空心三角…

【计算机网络】UDP/TCP协议

文章目录 :peach:1 UDP协议:peach:1.1 :apple:UDP协议端格式:apple:1.2 :apple:UDP的特点:apple:1.3 :apple:UDP的缓冲区:apple:1.4 :apple:UDP使用注意事项:apple:1.5 :apple:基于UDP的应用层协议:apple: 2 :peach:TCP协议:peach:2.1 :apple:TCP协议端格式:apple:2.2 :apple:确…