Unity 圆形循环复用滚动列表
一.在上一篇垂直循环复用滚动列表的基础上,扩展延申了圆形循环复用滚动列表。实现此效果需要导入垂直循环复用滚动列表里面的类。
1.基础类
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.UIElements;/// <summary>
/// 环形的网格布局;
/// 让子对象摆成一个环形;
/// </summary>
public class CricleGrid : MonoBehaviour
{/// <summary>/// 是否是自动刷新模式,否则的话需要手动调用刷新;/// </summary>public bool IsAutoRefresh = true;/// <summary>/// 是否发生过改变;/// </summary>private bool IsChanged = false;/// <summary>/// 上一次检查的数量;/// </summary>int LastCheckCount = 0;/// <summary>/// Update每帧调用一次/// </summary>void Update(){检查是否需要自动刷新;if (!IsAutoRefresh)return;if (!IsChanged){//检测子物体有没有被改变;GetChidList();int length = ListRect.Count;if (length != LastCheckCount){LastCheckCount = length;IsChanged = true;}//此时刷新大小和位置;if (IsChanged)ResetSizeAndPos();}elseRefreshAll();}private void OnValidate(){//编辑器下每一次更改需要实时刷新;RefreshAll();}/// <summary>/// 全部刷新;/// </summary>public void RefreshAll(){GetChidList();ResetSizeAndPos();}/// <summary>/// 当下激活的Rect;/// </summary>public List<RectTransform> ListRect = new List<RectTransform>(4);List<RectTransform> tempListRect = new List<RectTransform>(4);/// <summary>/// 获取父节点为本身的子对象/// </summary>void GetChidList(){ListRect.Clear();GetComponentsInChildren(false, tempListRect);int length = tempListRect.Count;for (int i = 0; i < length; i++){var r = tempListRect[i];if (r.transform.parent != transform) continue;ListRect.Add(r);}}/// <summary>/// 网格大小;/// </summary>public Vector2 CellSize = new Vector2();/// <summary>/// 半径;/// </summary>public float Radius = 1;/// <summary>/// 起始角度;/// </summary>[Range(0f, 360f)][SerializeField]float m_StartAngle = 30;/// <summary>/// 起始角度;/// </summary>public float StartAngle{get { return m_StartAngle; }set{m_StartAngle = value;IsChanged = true;}}/// <summary>/// 间隔角度;/// </summary>[Range(0f, 360f)][SerializeField]float m_Angle = 30;/// <summary>/// 间隔角度;/// </summary>public float Angle{get { return m_Angle; }set{m_Angle = value;IsChanged = true;}}public Dictionary<int, CricleScrollItemPosData> itemPosDic = new();public List<CricleScrollItemPosData> itemPosList = new();/// <summary>/// 重新将字节点设置大小;/// </summary>public void ResetSizeAndPos(){int length = ListRect.Count;for (int i = 0; i < length; i++){var tran = ListRect[i];tran.sizeDelta = CellSize;var v = GerCurPosByIndex(i);tran.anchoredPosition = new Vector2(v.x,v.y);tran.localEulerAngles = new Vector3(0,0, v.z);}}/// <summary>/// 返回第几个子对象应该所在的相对位置;/// </summary>public Vector3 GerCurPosByIndex(int index){//1、先计算间隔角度:(弧度制)float totalAngle = Mathf.Deg2Rad * (index * Angle + m_StartAngle);//2、计算位置Vector3 Pos = new Vector2(Radius * Mathf.Cos(totalAngle), Mathf.Sin(totalAngle) * Radius);Pos.z = index * Angle + m_StartAngle + 180;return Pos;}public ScrollRect scrollRect;public List<object> list = new();public GameObject item;private List<CustomScrollItemMono> scrollTestItems = new();private int startIndex;private int endIndex;private int showItemCount = 10;private void InitItemsPos() {int n = (int)(360f / Angle);for (int i = 0; i < list.Count; i++){var v = GerCurPosByIndex(i);CricleScrollItemPosData data = new CricleScrollItemPosData();data.AnchoredPosition = new Vector3(v.x, v.y);data.LocalEulerAngles = new Vector3(0, 0, v.z);itemPosDic.Add(i, data);itemPosList.Add(data);//if (i < n)//{// var v = GerCurPosByIndex(i);// CricleScrollItemPosData data = new CricleScrollItemPosData();// data.AnchoredPosition = new Vector3(v.x, v.y);// data.LocalEulerAngles = new Vector3(0, 0, v.z);// itemPosDic.Add(i, data);// itemPosList.Add(data);//}//else //{// int temp = i % n;// int m = (i + 1) / n;// CricleScrollItemPosData d = new CricleScrollItemPosData();// d.AnchoredPosition = itemPosDic[temp].AnchoredPosition;// d.LocalEulerAngles.z += itemPosDic[temp].LocalEulerAngles.z + 360 * m;// itemPosDic.Add(i, d);// itemPosList.Add(d);//}}Debug.Log($"InitItemsPos ");}private void InitShowItems(){for (int i = 0; i < showItemCount; i++){GameObject obj = Instantiate(item, transform);obj.transform.name = i.ToString();obj.SetActive(true);CustomScrollItemMono testItem = obj.GetComponent<CustomScrollItemMono>();testItem.Init(i, list[i]);scrollTestItems.Add(testItem);}item.SetActive(false);}private float eulerAnglersZ;private float preA = 1;public ScrollRect ScrollRect;private RectTransform Content;/// <summary>/// 用这个初始化/// </summary>void Start(){for (int i = 0; i < 100; i++){list.Add(new ScrollTestData() { ID = i });}Content = ScrollRect.content;Content.sizeDelta = new Vector2(500, (100 * Angle / 360 + StartAngle % 360 / 360f) * 2 * Mathf.PI * Radius);InitItemsPos();InitShowItems();RefreshAll();}private void Awake(){scrollRect.horizontal = false;scrollRect.vertical = true;scrollRect.onValueChanged.AddListener((value) =>{float offset = Mathf.Abs(preA - value.y);float aa = (offset) * ((100 - 6) * Angle);if (scrollRect.velocity.y > 0) //手指上滑 {transform.localEulerAngles -= new Vector3(0,0, aa);eulerAnglersZ += aa;}else if (scrollRect.velocity.y < 0)//手指下滑 {transform.localEulerAngles += new Vector3(0, 0, aa);eulerAnglersZ -= aa;}preA = value.y;for (int i = startIndex; i < itemPosList.Count; i++){if (i + 1 < itemPosList.Count){if (scrollRect.velocity.y > 0)//手指上滑 {var targetY = itemPosList[i + 1].LocalEulerAngles.z - 180;//Debug.Log($"ccc y {y} targetY {targetY} startIndex {startIndex} Z {transform.localEulerAngles.z}");if (eulerAnglersZ + StartAngle >= targetY){startIndex = i + 1;endIndex = startIndex + showItemCount - 1;break;}}else if (scrollRect.velocity.y < 0)//手指下滑{if (startIndex > 0 && startIndex < itemPosDic.Count){var targetY = itemPosDic[startIndex].LocalEulerAngles.z - 180;if (eulerAnglersZ + StartAngle <= targetY){startIndex = i - 1;endIndex = startIndex + showItemCount - 1;break;}}}}}//Debug.Log($"bbb startIndex {startIndex} endIndex {endIndex}");if (startIndex > 100 - showItemCount) {startIndex = 100 - showItemCount;}if (endIndex >= itemPosDic.Count) { return; }int index = 0;for (int i = startIndex; i < endIndex + 1; i++){if (index < scrollTestItems.Count && i < itemPosDic.Count){var item = scrollTestItems[index];item.Init(i, list[i]);var rect = item.gameObject.GetComponent<RectTransform>();rect.anchoredPosition3D = itemPosDic[i].AnchoredPosition;rect.localEulerAngles = itemPosDic[i].LocalEulerAngles;index += 1;}}});}public class CricleScrollItemPosData{public Vector3 AnchoredPosition;public Vector3 LocalEulerAngles;}}
2.UI目录
3.item克隆体,挂载脚本
4.按照图示,把CricleGrid脚本,挂在Items节点下,调整各个参数,运行即可。
相关文章:

Unity 圆形循环复用滚动列表
一.在上一篇垂直循环复用滚动列表的基础上,扩展延申了圆形循环复用滚动列表。实现此效果需要导入垂直循环复用滚动列表里面的类。 1.基础类 using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using …...

聚水潭数据无缝集成到金蝶云星空的实现方案
聚水潭数据集成到金蝶云星空:聚水潭调拨对接金蝶直接调拨ok 在企业信息化管理中,数据的高效流动和准确对接是实现业务流程顺畅运行的关键。本文将分享一个具体的系统对接集成案例——如何通过轻易云数据集成平台,将聚水潭的数据无缝集成到金…...

虚拟机断网没有网络,需清理内存,删除后再重启
进入NetworkManager可能没权限,设置权限777 to...

[c++11(二)]Lambda表达式和Function包装器及bind函数
1.前言 Lambda表达式着重解决的是在某种场景下使用仿函数困难的问题,而function着重解决的是函数指针的问题,它能够将其简单化。 本章重点: 本章将着重讲解lambda表达式的规则和使用场景,以及function的使用场景及bind函数的相关使…...

基于字节大模型的论文翻译(含免费源码)
基于字节大模型的论文翻译 源代码: 👏 star ✨ https://github.com/boots-coder/LLM-application 展示 项目简介 本项目是一个基于大语言模型(Large Language Model, LLM)的论文阅读与翻译辅助工具。它通过用户界面(…...

Mysql语法之DQL查询的多行函数
Mysql的多行函数和分组 目录 Mysql的多行函数和分组多行函数概念常用的多行函数 数据分组概念语法where和having的区别 语句关键字及执行顺序语句关键字执行顺序 实际操作基本语句格式和多行操作筛选语句格式 多行函数 概念 不管函数处理多少条,只返回一条记录&…...

OpenSSL 心脏滴血漏洞(CVE-2014-0160)
OpenSSL 心脏滴血漏洞(CVE-2014-0160) Openssl简介: 该漏洞在国内被译为"OpenSSL心脏出血漏洞”,因其破坏性之大和影响的范围之广,堪称网络安全里程碑事件。 OpenSSL心脏滴血漏洞的大概原理是OpenSSL在2年前引入了心跳(hearbea0机制来维特TS链接的…...

监控视频汇聚融合云平台一站式解决视频资源管理痛点
随着5G技术的广泛应用,各领域都在通信技术加持下通过海量终端设备收集了大量视频、图像等物联网数据,并通过人工智能、大数据、视频监控等技术方式来让我们的世界更安全、更高效。然而,随着数字化建设和生产经营管理活动的长期开展࿰…...

ElasticSearch 数据同步
1、同步调用 操作步骤: 管理系统新增酒店数据添加到数据库调用 ES 更新文档接口,同步数据库的数据到 ES 文档 流程图: 特点: 优点:实现简单,粗暴缺点:业务耦合度高 2、异步消息通知 操作步骤…...

MyBatis-Plus中isNull与SQL语法详解:处理空值的正确姿势
目录 前言1. 探讨2. 基本知识3. 总结 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 基本的Java知识推荐阅读: java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全&#x…...

RabbitMQ个人理解与基本使用
目录 一. 作用: 二. RabbitMQ的5中队列模式: 1. 简单模式 2. Work模式 3. 发布/订阅模式 4. 路由模式 5. 主题模式 三. 消息持久化: 消息过期时间 ACK应答 四. 同步接收和异步接收: 应用场景 五. 基本使用 ÿ…...

Python球球大作战
系列文章 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…...

入侵他人电脑,实现远程控制(待补充)
待补充 在获取他人无线网网络密码后,进一步的操作是实现入侵他人电脑,这一步需要获取对方的IP地址并需要制作自己的代码工具自动化的开启或者打开对方的远程访问权限。 1、获取IP地址(通过伪造的网页、伪造的Windows窗口、hook,信…...

数据分析实战—IMDB电影数据分析
1.实战内容 1.加载数据到movies_df,输出前5行,输出movies_df.info(),movies_df.describe() # (1)加载数据集,输出前5行 #导入库 import pandas as pd import numpy as np import matplotlib import matplotlib.pyplo…...
Google guava 最佳实践 学习指南之08 `BiMap`(双向映射)
guava 最佳实践 学习指南 Google Guava 库中的 BiMap(双向映射)是一种特殊的映射类型,它维护了映射的反向视图,并确保不存在重复值,且始终可以安全地使用值获取对应的键。以下是关于 Guava BiMap 的一些介绍和用法&am…...
【设计模式】空接口
(空)接口的用法总结 接口用于定义某个类的特定能力或特性。在工作流或任务管理系统中,接口可以帮助标识哪些任务可以在特定阶段执行。通过实现这些接口,任务类可以被标识为在相应的阶段可以执行,从而在验证和执行逻辑…...

Grad-CAM-解释CNN决策过程的可视化技术
Grad-CAM(Gradient-weighted Class Activation Mapping)是一种用于解释卷积神经网络(CNN)决策过程的可视化技术。其核心思想是通过计算分类分数相对于网络确定的卷积特征的梯度,来识别图像中哪些部分对分类结果最为重要…...
前后端学习中本周遇到的内容
一、RequiresPermissions注解 例如: RequiresPermissions("demo:staff:save") void saveStaff(); 权限控制,要求含有demo:staff:save的权限才能执行方法saveStaff()。 二、遇到的细节问题 在进行增删改查时,发送http请求时&…...

基于海思soc的智能产品开发(巧用mcu芯片)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于开发车规级嵌入式软件的同学来说,socmcu这样的组合,他们并不陌生。但是传统的工业领域,比如发动机、医疗或…...

批量DWG文件转dxf(CAD图转dxf)——c#插件实现
此插件可将指定文件夹及子文件夹下的dwg文件批量转为dxf文件。 (使用方法:命令行输入 “netload” 加载插件,然后输入“dwg2dxf”运行,选择文件夹即可。) 生成dxf在此新建的文件夹路径下,包含子文件夹内的…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...