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 :…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
