Unity CircleLayoutGroup 如何实现一个圆形自动布局组件
文章目录
- 简介
- 实现原理
- Editor 编辑器
简介
Unity中提供了三种类型的自动布局组件,分别是Grid Layou Group、Horizontal Layout Group、Vertical Layout Group,本文自定义了一个圆形的自动布局组件Circle Layout Group,如图所示:

Radius:Circle圆的半径Angle Delta:两个元素之间的角度差Start Direction:开始布局的方向(上、下、左、右)Auto Refresh:是否自动刷新,开启后当子物体数量发生变化时自动刷新布局Control Child Size:是否控制元素的大小Child Size:控制元素大小





实现原理
已知圆的中心点(x0, y0),半径radius ,通过以下公式求得角度a的圆上的点坐标位置(x,y):
float x = x0 + radius * Mathf.Cos(angle * Mathf.PI / 180f);
float y = y0 + radius * Mathf.Sin(angle * Mathf.PI / 180f);
在这里我们的子物体元素以其父级为圆心,所以不需要考虑(x0,y0):
float x = radius * Mathf.Cos(angle * Mathf.PI / 180f);
float y = radius * Mathf.Sin(angle * Mathf.PI / 180f);
三角函数原理:
Sin正弦:y(对边) / radius(斜边)
Cos余弦:x(邻边)/ radius(斜边)
以右侧为0度起点,当方向为上方时加90度,当方向为左侧时加180度,当方向为下方时加270度,并根据角度差和元素的层级顺序计算其角度。
代码实现如下:
using UnityEngine;
using System.Collections.Generic;namespace SK.Framework.UI
{/// <summary>/// 圆形自动布局组件/// </summary>public class CircleLayoutGroup : MonoBehaviour{//半径[SerializeField] private float radius = 100f;//角度差[SerializeField] private float angleDelta = 30f;//开始的方向 0-Right 1-Up 2-Left 3-Down[SerializeField] private int startDirection = 0;//是否自动刷新布局[SerializeField] private bool autoRefresh = true;//是否控制子物体的大小[SerializeField] private bool controlChildSize = true;//子物体大小[SerializeField] private Vector2 childSize = Vector2.one * 100f;//缓存子物体数量private int cacheChildCount;private void Start(){cacheChildCount = transform.childCount;RefreshLayout();}private void Update(){//开启自动刷新if (autoRefresh){//检测到子物体数量变动if (cacheChildCount != transform.childCount){//刷新布局RefreshLayout();//再次缓存子物体数量cacheChildCount = transform.childCount;}} }/// <summary>/// 刷新布局/// </summary>public void RefreshLayout(){//获取所有非隐藏状态的子物体List<RectTransform> children = new List<RectTransform>();for (int i = 0; i < transform.childCount; i++){Transform child = transform.GetChild(i);if (child.gameObject.activeSelf){children.Add(child as RectTransform);}}//形成的扇形的角度 = 子物体间隙数量 * 角度差float totalAngle = (children.Count - 1) * angleDelta;//总角度的一半float halfAngle = totalAngle * 0.5f;//遍历这些子物体for (int i = 0; i < children.Count; i++){RectTransform child = children[i];/* 以右侧为0度起点 * 方向为Up时角度+90 Left+180 Down+270* 方向为Right和Up时 倒序计算角度 * 确保层级中的子物体按照从左到右、从上到下的顺序自动布局 */float angle = angleDelta * (startDirection < 2 ? children.Count - 1 - i : i) - halfAngle + startDirection * 90f;//计算x、y坐标float x = radius * Mathf.Cos(angle * Mathf.PI / 180f);float y = radius * Mathf.Sin(angle * Mathf.PI / 180f);//为子物体赋值坐标Vector2 anchorPos = child.anchoredPosition;anchorPos.x = x;anchorPos.y = y;child.anchoredPosition = anchorPos;//控制子物体大小if (controlChildSize){child.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, childSize.x);child.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, childSize.y);}}}}
}
Editor 编辑器
通过上述代码可以实现Runtime运行时的布局自动刷新,想要在Editor编辑环境编辑时自动刷新还需要自定义Editor编辑器,代码如下:
#if UNITY_EDITOR[CustomEditor(typeof(CircleLayoutGroup))]public class CircleLayoutGroupEditor : Editor{private enum Direction{Right = 0,Up = 1,Left = 2,Down = 3}private CircleLayoutGroup circleLayoutGroup;private SerializedProperty radius;private SerializedProperty angleDelta;private SerializedProperty startDirection;private SerializedProperty autoRefresh;private SerializedProperty controlChildSize;private SerializedProperty childSize;private Direction direction;private void OnEnable(){circleLayoutGroup = target as CircleLayoutGroup;radius = serializedObject.FindProperty("radius");angleDelta = serializedObject.FindProperty("angleDelta");startDirection = serializedObject.FindProperty("startDirection");autoRefresh = serializedObject.FindProperty("autoRefresh");controlChildSize = serializedObject.FindProperty("controlChildSize");childSize = serializedObject.FindProperty("childSize");direction = (Direction)startDirection.intValue;circleLayoutGroup.RefreshLayout();}public override void OnInspectorGUI(){float newRadius = EditorGUILayout.FloatField("Radius", radius.floatValue);if (newRadius != radius.floatValue){Undo.RecordObject(target, "Radius");radius.floatValue = newRadius;IsChanged();}float newAngleDelta = EditorGUILayout.FloatField("Angle Delta", angleDelta.floatValue);if (newAngleDelta != angleDelta.floatValue){Undo.RecordObject(target, "Angle Delta");angleDelta.floatValue = newAngleDelta;IsChanged();}Direction newDirection = (Direction)EditorGUILayout.EnumPopup("Start Direction", direction);if (newDirection != direction) {Undo.RecordObject(target, "Start Direction");direction = newDirection;startDirection.intValue = (int)direction;IsChanged();}bool newAutoRefresh = EditorGUILayout.Toggle("Auto Refresh", autoRefresh.boolValue);if (newAutoRefresh != autoRefresh.boolValue){Undo.RecordObject(target, "Angle Refresh");autoRefresh.boolValue = newAutoRefresh;IsChanged();}bool newControlChildSize = EditorGUILayout.Toggle("Control Child Size", controlChildSize.boolValue);if (newControlChildSize != controlChildSize.boolValue){Undo.RecordObject(target, "Control Child Size");controlChildSize.boolValue = newControlChildSize;IsChanged();}if (controlChildSize.boolValue){Vector2 newChildSize = EditorGUILayout.Vector2Field("Child Size", childSize.vector2Value);if (newChildSize != childSize.vector2Value){Undo.RecordObject(target, "Child Size");childSize.vector2Value = newChildSize;IsChanged();}}}private void IsChanged(){if (GUI.changed){serializedObject.ApplyModifiedProperties();EditorUtility.SetDirty(target);circleLayoutGroup.RefreshLayout();}}}
#endif
工具已上传SKFramework框架Package Manager中:

相关文章:
Unity CircleLayoutGroup 如何实现一个圆形自动布局组件
文章目录简介实现原理Editor 编辑器简介 Unity中提供了三种类型的自动布局组件,分别是Grid Layou Group、Horizontal Layout Group、Vertical Layout Group,本文自定义了一个圆形的自动布局组件Circle Layout Group,如图所示: Ra…...
springcloud+nacos+gateway案例
一、先搭建好springcloudnacos项目地址:https://javazhong.blog.csdn.net/article/details/128899999二、spring cloud gateway简述Spring Cloud Gateway 是Spring Cloud家族中的一款API网关。Gateway 建立在 Spring Webflux上,目标是提供一个简洁、高效的API网关&a…...
实习这么久,你知道Maven是如何从代码仓库中找到需要的依赖吗?
目录 碎碎念 Maven是如何找到代码仓库里需要的依赖的? 如何根据坐标在本地仓库中寻找所需要的依赖? 如何根据坐标在远程仓库中寻找所需要的依赖? Maven 如何使用 HTTP 或 HTTPS 协议从远程仓库中获取依赖项,请详细解释其原理…...
低代码/零代码的快速开发框架
目前国内主流的低代码开发平台有:宜搭、简道云、明道云、云程、氚云、伙伴云、道一云、JEPaaS、华炎魔方、搭搭云、JeecgBoot 、RuoYi等。这些平台各有优劣势,定位也不同,用户可以根据自己需求选择。 一、阿里云宜搭 宜搭是阿里巴巴集团在20…...
C# 中常见的设计模式
设计模式是一套被广泛应用于软件设计的最佳实践,它们可以帮助开发者解决特定的问题,提高代码的可重用性、可读性和可维护性。本文将介绍 C# 中常见的几种设计模式,并提供相应的示例代码。 工厂模式 工厂模式是一种创建型设计模式,…...
promethues/servicemonitor
目录 1.promethues 能保证源源不断地采集/metrics 信息吗?每次都是最新的吗 2.部署servicemonitor 的作用是什么? 3.pod 部署采集数据直接上报promthues ,不通过servicemonitor 可以吗? 4.你说的"此外,如果部署…...
postman使用简介
1、介绍 postman是一款功能强大的网页调试和模拟发送HTTP请求的Chrome插件,支持几乎所有类型的HTTP请求 2、下载及安装 官方文档:https://www.getpostman.com/docs/v6/ chrome插件:chrome浏览器应用商店直接搜索添加即可(需墙&…...
@DS注解在事务中实现数据源的切换@DS在事务中失效【已解决】
在Springboot的application.yml中的配置: spring:datasource:url: jdbc:mysql://localhost:3306/test2?serverTimezoneUTC&useUnicodetrue&characterEncodingutf8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootdynamic:primar…...
Java I/O之文件系统
一、全文概览 在学习文件系统之前,需要了解下Java在I/O上的发展史:在Java7之前,打开和读取文件需要编写特别笨拙的代码,涉及到很多的InputStream、OutputStream等组合起来使用,每次在使用时或许都需要查一下文档才能记…...
Mysql元数据获取方法(information_schema绕过方法)
前提:如果waf或其它过滤了information_schema关键字,那我们该如何获取元数据呢?能够代替information_schema的有:sys.schema_auto_increment_columnssys.schema_table_statistics_with_bufferx$schema_table_statistics_with_buff…...
Eclipse快捷键
* 1.补全代码的声明:alt /* 2.快速修复: ctrl 1 * 3.批量导包:ctrl shift o* 4.使用单行注释:ctrl /* 5.使用多行注释: ctrl shift / * 6.取消多行注释:ctrl shift \* 7.复制指定行的代码:ctrl a…...
java ssm自习室选座预约系统开发springmvc
人工管理显然已无法应对时代的变化,而自习室选座预约系统开发能很好地解决这一问题,既能提高人力物力,又能提高预约选座的知名度,取代人工管理是必然趋势。 本自习室选座预约系统开发以SSM作为框架,JSP技术,…...
分享我从功能测试转型到测试开发的真实故事
由于这段时间我面试了很多家公司,也经历了之前公司的不愉快。所以我想写一篇文章来分享一下自己的面试体会。希望能对我在之后的工作或者面试中有一些帮助,也希望能帮助到正在找工作的你。 找工作 我们总是草率地进入一个自己不了解的公司工作…...
TypeScript快速入门———(二)TypeScript常用类型
文章目录概述1 类型注解2 常用基础类型概述3.原始类型4 数组类型5 类型别名6.函数类型7 对象类型8 接口9 元组10 类型推论11 类型断言12 字面量类型13 枚举14 any 类型15 typeof概述 TypeScript 是 JS 的超集,TS 提供了 JS 的所有功能,并且额外的增加了…...
Mac M1 使用Centos8➕VMware Fusion进行静态网络配置
大部分的流程网络上面都有当我们已经下载好mac m1版的Centos8链接: https://pan.baidu.com/s/1UTl4Lo-_c17s-PDj3dA6kA 提取码: 7xh2 和VMware Fusionhttps://www.vmware.com/cn/products/fusion.html之后就可以进行安装了在导入过后 记得将硬盘和内存都设置好了 记得在关机状态…...
RadGraph: Extracting Clinical Entities and Relations from Radiology Reports代码
文章来源:NeurIPS 文章类别:IE(Information Extraction) RadGraph主要基于dygie,主要文件为inference.py。 inference.py: 1、get_file_list(data_path) def get_file_list(path):file_list [item for item in glob.glob(f&q…...
13. OPenGL与QT界面元素交互控制图形渲染
1. 说明: 前面文章中讲到的 OPenGL 渲染都是在页面加载完成即立刻渲染的,如果向控制图形渲染的时间,可以在QT界面中添加一些元素来进行控制。此时需要用到OPenGL当中的makeCurrent(),update(),doneCurrent()函数。 效果展示: ope…...
高通平台开发系列讲解(USB篇)libuvc详解
文章目录 一、什么是UVC二、UVC拓扑结构三、libuvc的预览时序图沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍libuvc。 一、什么是UVC UVC,全称为:USB video(device) class。 UVC是微软与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标…...
ICC2:set_route_opt_target_endpoints
route_opt阶段通过指定endpoint/driver pin list的方式执行incremental优化。 set_route_opt_target_endpoints [-setup_endpoints file] [-setup_endpoints_collection pin_list] [-hold_endpoints file] [-hold_endpoints_collection pin_list] [-ldrc_objects fil…...
5、小程序面试题
1, 小程序页面有哪些生命周期函数onLoad: 页面加载onReady: 页面初次渲染完成onShow: 页面显示onHide: 页面隐藏onUnload: 页面卸载2, 一页小程序页面有哪些文件组成,分别有什么作用.wxml: 使用微信框架设计的一套组件构建页面结构.wxss: 用于设置页面样式, 和css基本一致.js :…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
