unity UGUI无限循环滚动居中

news2024/11/17 1:56:11

最近在做一个ui循环滚动的功能,网上找了半天脚本感觉都和我实际需求不太符合,自己花费一些时间完成了这个功能记录一下。下面开始正题
,我是采用unity自带组件Scroll View来完成,首先设置Scroll View如下图
我是横屏你可以根据情况选择你的
面板层级结构如下
层级面板结构
然后创建一个预制体,预制体需要锚点到左侧中心点,设置为起始点,设置完成后把这个图片随便放个层级不要在本层级,不要影响后面生成。
红色就是UI
然后开始编写代码,我就直接贴了,不懂可以看一下注释,因为我是水平所以判断用的都是x轴,如果你是垂直你改成y稍微修改一下代码就可以了,差别应该不大。

using DG.Tweening;
using System.Collections;
using System.Collections.Generic;

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class LoopScroll : MonoBehaviour,IBeginDragHandler  
{
    public List<Sprite> photographList;
    [Header("中心点")]
    public Transform Centre;
    private Vector3 startPos, endPos;
    [Header("预制体")]
    public GameObject item;
    [Header("预制体父级")]
    public Transform Content;
    [HideInInspector]
    public List<Transform> itemList;
    bool isDrag = false, isAdsorption;
    float MaxDis, MinDis;
    [Header("间隔距离")]
    public float SpacingDistance = 100;
    [Header("缩放倍数")]
    public float Scale =1;
    Transform tempCentre;   
    public Text tempCentreName;
    private void Awake()
    {
        instantiationItem();
    }
    void Start()
    {            
        isDrag = true;
        //设置第一个坐标与最后一个坐标位置
        startPos = itemList[0].position;
        endPos = itemList[itemList.Count - 1].position;
        startPos.x -= itemList[0].GetComponent<RectTransform>().rect.width /2;
        endPos.x += itemList[0].GetComponent<RectTransform>().rect.width / 2;
      
        //求出最远距离
        for (int i = 0; i < itemList.Count; i++)
        {
            var dis = Vector3.Distance(itemList[i].position, Centre.position);
            if (dis > MaxDis)
            {
                MaxDis = dis;
                MinDis = dis;
            }
        }
    
    }
    void instantiationItem()//生成预制体设置初始坐标
    {
        for (int i = 0; i < photographList.Count; i++)
        {
            var t = Instantiate(item, Content);
            t.GetComponent<Image>().sprite = photographList[i];
            t.name = photographList[i].name;
            var pos = new Vector3((t.GetComponent<RectTransform>().rect.width + SpacingDistance) * (i), 0, 0);
            pos.x += t.GetComponent<RectTransform>().rect.width;
            t.GetComponent<RectTransform>().anchoredPosition = pos;
            itemList.Add(t.transform);
        }

    }
    void Islimit() //设置坐标切换与列表内元素与面板层级切换 保证层级与列表内数据同步
    {
        if (isDrag)
        {
            for (int i = 0; i < itemList.Count; i++)
            {
                if (itemList[i].position.x < startPos.x)
                {
                    itemList[i].position = itemList[itemList.Count - 1].position + new Vector3(SpacingDistance + itemList[0].GetComponent<RectTransform>().rect.width, 0, 0);
                    var temp = itemList[i];
                    itemList.Remove(itemList[i]);
                    itemList.Add(temp);
                    temp.SetSiblingIndex(itemList.Count - 1);
                }
                if (itemList[i].position.x > endPos.x)
                {
                    itemList[i].position = itemList[0].position - new Vector3(SpacingDistance + itemList[0].GetComponent<RectTransform>().rect.width, 0, 0);
                    var temp = itemList[i];
                    itemList.Remove(itemList[i]);
                    itemList.Insert(0, temp);
                    temp.SetSiblingIndex(0);
                }
            }
        }

    }

    void ScaleDistance()//根据百分比设置缩放动画
    {
        for (int i = 0; i < itemList.Count; i++)
        {
            double dis = Vector3.Distance(itemList[i].position, Centre.position) / MaxDis;
            if (!double.IsInfinity(dis))
            {
                if (dis > 0)
                {
                    if (dis<0.05f)
                    {
                        itemList[i].localScale = Vector3.one * ((1f - (float)dis) * Scale) ;
                    }
                    else
                    {
                        itemList[i].localScale = Vector3.one * ((1f - (float)dis) * Scale) * 0.8f;
                    }
                 
                }

            }

        } 
    }
    Tween tw;
    void Adsorption() //停止滑动进行吸附
    {
        for (int i = 0; i < itemList.Count; i++)//找出距离中心点最近的
        {
            float dis = Vector3.Distance(itemList[i].position, Centre.position);

            if (dis < MinDis)
            {

                tempCentre = itemList[i];
                tempCentreName.text = itemList[i].name;
            }
            MinDis = dis;
        }
        if (GetComponent<ScrollRect>().velocity.x==0 && isAdsorption == false)//判断当前滑动结束
        {
          
            //计算当前距离中心差多远后 进行吸附
            if (tempCentre)
            {
                var dis = Centre.position - tempCentre.position;
                tw = Content.DOMoveX(Content.position.x + dis.x, 0.5f);
                tempCentre = null;
                isAdsorption = true;
            }
            else
            {
                isAdsorption = false;
            }
            
        }
        else if (GetComponent<ScrollRect>().velocity.x!=0)//如果在吸附过程中点击拖拽强制结束吸附动画
        {
            isAdsorption = false;
            tw.Kill();
        }
    }
    // Update is called once per frame  
    void Update()
    {
        Islimit();
        ScaleDistance();
        Adsorption();
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        tw.Kill();

    }
}

下面这个是脚本设置,主要关注的就是公开的变量我都有注释,结合上面的面板图很轻易就能看出来,第一个就是循环图片,间隔距离是两个图片之间的距离,缩放倍数是中间最大是多少倍,根据你工程设置,默认设置1就可以了,最后面的text是显示居中ui的名字,名字的设置是根据图片名称来的。
在这里插入图片描述
运行后这三个内容层级都会同步,可以进行一些你想要的操作
在这里插入图片描述

最后说下使用了Dotween插件,吸附居中功能我是感觉有点延迟,但是还没找到更好的方法,如果大家有更好的方法欢迎大佬留言,完成上面的设置就可以畅快玩耍了~~

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

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

相关文章

zookeeper的安装部署

目录 简介 Zookeeper架构设计及原理 1.Zookeeper定义 2.Zookeeper的特点 3.Zookeeper的基本架构 4.Zookeeper的工作原理 5.Zookeeper的数据模型 &#xff08;1&#xff09;临时节点 &#xff08;2&#xff09;顺序节点 &#xff08;3&#xff09;观察机制 Zookeeper集…

ICC2/innovus merge gds

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 calibre merge gds的方法示例参考往期文章: Calibre Merge GDS ICC2: write_gds -merge_files "std.gds sram.gds io.gds ip.gds ... ..." innovus: streamout -…

Postman接口Mock Servier服务器

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 应用场景&#xff1a;后端的接口还没有开发完成&#xff0c;前端的业务需要调用后端的接口&#xff0c;可以使用mock模拟。 一…

开发板上网详细教程

开发板上网详细教程 PC端操作开发板操作 写在前面 今天想配置开发板的boa服务器&#xff0c;需要下载sudo apt-get install bison flex&#xff0c;但是一直报错&#xff0c;就蒙蔽了&#xff0c;后来想想真不应该啊&#xff0c;电脑和开发板通信没问题&#xff0c;但也只是如此…

VueEcharts的使用简解以及常用网站

目录 一&#xff1a;前言 二&#xff1a;实现 1、安装echarts依赖 2、创建图表 1&#xff09;全局引入 2&#xff09;按需引入 三&#xff1a;结尾 一&#xff1a;前言 VueEcharts 是项目开发中可视化的一个重要知识部分。其涵盖了柱状图&#xff0c;饼状图&#xff0c;…

LoadRunner脚本编写之三(事务函数)

关于脚本的这块&#xff0c;前两篇都在讲C语言&#xff0c;其实&#xff0c;要整理点实用的东西挺难&#xff0c;在应用中多对录制的脚本分析&#xff0c;但对于新手学脚本确实无从下手。 先贴一个脚本&#xff1a; 完整代码&#xff1a; 重点代码部分&#xff1a; Action(…

Redis快速入门(基础篇)

简介&#xff1a; 是一个高性能的 key-value数据库。 存在内存中 与其他 key-value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保持在磁盘中&#xff0c;重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类…

浅了解下:运营商大数据如何挖掘电销同行网站,APP,精准获客 ?

今天我们要讲的是运营商精准大数据营销。运营商精准大数据营销只是精准营销的一种&#xff0c;精准营销筛选包含了电话营销这个词。那么电话营销如何通过运营商大数据找到精准的客户&#xff1f;电销如何通过大数据找到准确的客户来源&#xff1f; 在全网时代&#xff0c;大数…

TYUST-RM2023-NewMaker哨兵视觉代码

目录 1 TYUST-RM2023-NewMaker哨兵视觉代码 1.1 说明 1.2 算法设计 1.3 识别思路 TYUST-RM2023-NewMaker哨兵视觉代码 说明 本套代码是太原科技大学NewMaker战队2023赛季哨兵开源代码 本套代码主要含有&#xff1a;TYUST-RM2023赛季哨兵视觉代码&#xff0c;主要模块…

科研学习|科研软件——SPSS:卡方检验(交叉表)

第一步 打开SPSS软件&#xff0c;在工具栏中选中【打开-文件-数据】&#xff0c;然后选择一份要打开的数据表(如图所示)。 第二步 在工具栏中找到【分析-描述统计-交叉表】打开交叉表对话框(如图所示)。 第三步 接着将【行-列】相关变量放在对应对话框中(如图所示)。 第四步 在…

ubuntu 20.04+ORB_SLAM3 安装配库教程

目录 安装ros(如果只是运行ORB-SLAM3&#xff0c;可以跳过安装)0. ros 安装教程1. 安装opencv2. 安装Pangolin3. 安装Eigen34.安装Python & libssl-dev5.安装boost库6.安装ceres库&#xff08;不必须&#xff09;7.安装Sophus库&#xff08;不必须&#xff09;8. 安装g20库…

科研学习|研究方法——逻辑回归系数的显著性检验(python实现)

1. 背景 回归方程与回归系数的显著性检验 2. statsmodels 库 statsmodels库可以用来做逻辑回归、线性回归。并且会在summary中给出显著性检验的结果。最终我们想要的就是如下图的报告。 3. 计算过程 如果我们使用的sklearn构建的逻辑回归就没有办法直接输出这个报告&#xff0c…

Xocde 升级15 或者 iOS17报错:

错误&#xff1a; Assertion failed: (false && "compact unwind compressed function offset doesnt fit in 24 bits"), function operator(), file Layout.cpp, line 5758. 翻译&#xff1a; 断言失败&#xff1a;&#xff08;false&&“压缩展开…

基于安卓android微信小程序的食谱大全系统

项目介绍 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个开发过程首先对食谱大全进行需求分析&#xff0c;得出食谱大全主要功能。接着对食谱大全进行总体设计和详细设计。总体设…

窗口管理工具 Mosaic mac中文版功能特点

MosAIc mac是一种窗口管理工具&#xff0c;可帮助您在计算机屏幕上有效地组织和管理多个应用程序窗口。它提供了一种直观的方式来调整和排列窗口&#xff0c;以最大化工作效率。 MosAIc mac窗口管理软件功能和特点 窗口布局&#xff1a;MosAIc允许您选择不同的窗口布局&#x…

SketchUp (草图大师) SU2023 中文版软件安装包下载地址及安装教程!

1.鼠标右键【SketchUp2023(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;选择【解压到SketchUp2023(64bit)】。 2.打开解压后的文件夹&#xff0c;鼠标右键【Setup】选择【以管理员身份运行】。 3.点击【Next】。 4.点击Install Language右边…

JVM查看内存新生代老年代回收情况,排查oom

jstat 命令 jstat - [-t] [-h] [ []] option&#xff1a;我们经常使用的选项有gc、gcutil vmid&#xff1a;java进程id interval&#xff1a;间隔时间&#xff0c;单位为毫秒 count&#xff1a;打印次数 每秒打印一次 jstat -gc 9162 1000S0C:年轻代第一个survivor的容量…

think5和fastadmin验证规则的使用

在fastadmin中使用验证规则只需要两步即可 第一步 首先在控制器中开启验证规则 protected $modelValidatetrue;//开启验证规则protected $modelSceneValidatetrue;//开启场景验证第二步 在 app\admin\validate 和控制器对应的 validate 中添加 验证规则以及场景验证 <?…

Blackmagic Design DaVinci Resolve Studio18(达芬奇调色剪辑)mac/win中文版

在影视制作领域&#xff0c;调色和剪辑是至关重要的环节&#xff0c;它们直接决定了作品的观感和质量。而Blackmagic Design DaVinci Resolve Studio18&#xff08;达芬奇调色剪辑&#xff09;作为业界领先的专业调色剪辑软件&#xff0c;以其出色的性能和强大的功能&#xff0…

SpringBoot项目集成发邮件功能

1&#xff1a;引入依赖2&#xff1a;配置设置3&#xff1a;授权码获取&#xff1a;4&#xff1a;核心代码5&#xff1a;postman模拟验证6&#xff1a;安全注意 1&#xff1a;引入依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>c…