当前位置: 首页 > news >正文

Unity CircleLayoutGroup 如何实现一个圆形自动布局组件

文章目录

  • 简介
  • 实现原理
  • Editor 编辑器


简介

Unity中提供了三种类型的自动布局组件,分别是Grid Layou GroupHorizontal Layout GroupVertical Layout Group,本文自定义了一个圆形的自动布局组件Circle Layout Group,如图所示:

Circle Layout Group

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

StartDirection:Right

StartDirection:Up

StartDirection:Left

StartDirection:Down

Auto Refresh

实现原理

已知圆的中心点(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中:

SKFramework Package Manager

相关文章:

Unity CircleLayoutGroup 如何实现一个圆形自动布局组件

文章目录简介实现原理Editor 编辑器简介 Unity中提供了三种类型的自动布局组件&#xff0c;分别是Grid Layou Group、Horizontal Layout Group、Vertical Layout Group&#xff0c;本文自定义了一个圆形的自动布局组件Circle Layout Group&#xff0c;如图所示&#xff1a; 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上&#xff0c;目标是提供一个简洁、高效的API网关&a…...

实习这么久,你知道Maven是如何从代码仓库中找到需要的依赖吗?

目录 碎碎念 Maven是如何找到代码仓库里需要的依赖的&#xff1f; 如何根据坐标在本地仓库中寻找所需要的依赖&#xff1f; 如何根据坐标在远程仓库中寻找所需要的依赖&#xff1f; Maven 如何使用 HTTP 或 HTTPS 协议从远程仓库中获取依赖项&#xff0c;请详细解释其原理…...

低代码/零代码的快速开发框架

目前国内主流的低代码开发平台有&#xff1a;宜搭、简道云、明道云、云程、氚云、伙伴云、道一云、JEPaaS、华炎魔方、搭搭云、JeecgBoot 、RuoYi等。这些平台各有优劣势&#xff0c;定位也不同&#xff0c;用户可以根据自己需求选择。 一、阿里云宜搭 宜搭是阿里巴巴集团在20…...

C# 中常见的设计模式

设计模式是一套被广泛应用于软件设计的最佳实践&#xff0c;它们可以帮助开发者解决特定的问题&#xff0c;提高代码的可重用性、可读性和可维护性。本文将介绍 C# 中常见的几种设计模式&#xff0c;并提供相应的示例代码。 工厂模式 工厂模式是一种创建型设计模式&#xff0c…...

promethues/servicemonitor

目录 1.promethues 能保证源源不断地采集/metrics 信息吗&#xff1f;每次都是最新的吗 2.部署servicemonitor 的作用是什么&#xff1f; 3.pod 部署采集数据直接上报promthues &#xff0c;不通过servicemonitor 可以吗&#xff1f; 4.你说的"此外&#xff0c;如果部署…...

postman使用简介

1、介绍 postman是一款功能强大的网页调试和模拟发送HTTP请求的Chrome插件&#xff0c;支持几乎所有类型的HTTP请求 2、下载及安装 官方文档&#xff1a;https://www.getpostman.com/docs/v6/ chrome插件&#xff1a;chrome浏览器应用商店直接搜索添加即可&#xff08;需墙&…...

@DS注解在事务中实现数据源的切换@DS在事务中失效【已解决】

在Springboot的application.yml中的配置&#xff1a; spring:datasource:url: jdbc:mysql://localhost:3306/test2?serverTimezoneUTC&useUnicodetrue&characterEncodingutf8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootdynamic:primar…...

Java I/O之文件系统

一、全文概览 在学习文件系统之前&#xff0c;需要了解下Java在I/O上的发展史&#xff1a;在Java7之前&#xff0c;打开和读取文件需要编写特别笨拙的代码&#xff0c;涉及到很多的InputStream、OutputStream等组合起来使用&#xff0c;每次在使用时或许都需要查一下文档才能记…...

Mysql元数据获取方法(information_schema绕过方法)

前提&#xff1a;如果waf或其它过滤了information_schema关键字&#xff0c;那我们该如何获取元数据呢&#xff1f;能够代替information_schema的有&#xff1a;sys.schema_auto_increment_columnssys.schema_table_statistics_with_bufferx$schema_table_statistics_with_buff…...

Eclipse快捷键

* 1.补全代码的声明&#xff1a;alt /* 2.快速修复: ctrl 1 * 3.批量导包&#xff1a;ctrl shift o* 4.使用单行注释&#xff1a;ctrl /* 5.使用多行注释&#xff1a; ctrl shift / * 6.取消多行注释&#xff1a;ctrl shift \* 7.复制指定行的代码&#xff1a;ctrl a…...

java ssm自习室选座预约系统开发springmvc

人工管理显然已无法应对时代的变化&#xff0c;而自习室选座预约系统开发能很好地解决这一问题&#xff0c;既能提高人力物力&#xff0c;又能提高预约选座的知名度&#xff0c;取代人工管理是必然趋势。 本自习室选座预约系统开发以SSM作为框架&#xff0c;JSP技术&#xff0c…...

分享我从功能测试转型到测试开发的真实故事

由于这段时间我面试了很多家公司&#xff0c;也经历了之前公司的不愉快。所以我想写一篇文章来分享一下自己的面试体会。希望能对我在之后的工作或者面试中有一些帮助&#xff0c;也希望能帮助到正在找工作的你。 找工作 我们总是草率地进入一个自己不了解的公司工作&#xf…...

TypeScript快速入门———(二)TypeScript常用类型

文章目录概述1 类型注解2 常用基础类型概述3.原始类型4 数组类型5 类型别名6.函数类型7 对象类型8 接口9 元组10 类型推论11 类型断言12 字面量类型13 枚举14 any 类型15 typeof概述 TypeScript 是 JS 的超集&#xff0c;TS 提供了 JS 的所有功能&#xff0c;并且额外的增加了…...

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代码

文章来源&#xff1a;NeurIPS 文章类别&#xff1a;IE(Information Extraction) RadGraph主要基于dygie&#xff0c;主要文件为inference.py。 inference.py&#xff1a; 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. 说明&#xff1a; 前面文章中讲到的 OPenGL 渲染都是在页面加载完成即立刻渲染的&#xff0c;如果向控制图形渲染的时间&#xff0c;可以在QT界面中添加一些元素来进行控制。此时需要用到OPenGL当中的makeCurrent(),update(),doneCurrent()函数。 效果展示&#xff1a; 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 :…...

Java特殊操作流

6 特殊操作流 6.1 标注输入输出流 System类中有两个静态的成员变量&#xff1a; public static final InputStream in&#xff1a;标准输入流&#xff0c;通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源public static final PrintStream out&#xff1a;标准输…...

如何用SCRM销售管理系统管理销售和做销售管理

每一家企业都在找适合自己公司的销售管理方法&#xff0c;实现销售目标和努力提高业绩。 我们常说&#xff0c;做好销售管理有很多路径和方法&#xff0c;但我们不知道从哪里开始&#xff1f;每个阶段我们该怎么办&#xff1f;如何有效管理销售团队&#xff1f;好的企企业微信…...

分享117个HTML婚纱模板,总有一款适合您

分享117个HTML婚纱模板&#xff0c;总有一款适合您 117个HTML婚纱模板下载链接&#xff1a;https://pan.baidu.com/s/1cC3I5cfh91-KmQj4nfSoPA?pwd9hod 提取码&#xff1a;9hod Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 import os import shutil import …...

VIVADO2022 sdk 工程创建流程

正点原子uart历程复现 create block design&#xff08;起名 为System&#xff09; -> open block design -> 号/IP catalog 中搜索zynq 双击打开&#xff0c; 将和pl相关的时钟都干掉 再auto 布线一下 把herarchy中的sources 中的system.bd右键、 无脑下一步导出 如…...

【MyBatis】源码学习 02 - Java 元注解以及 MyBatis @Param 注解分析

文章目录前言参考目录学习笔记1、Java 注解1.1、Java 元注解1.2、Java ElementType 枚举值1.3、自定义注解2、Param 注解分析2.1、Param 注解2.2、测试方法2.3、流程分析&#xff08;重点&#xff1a;ParamNameResolver&#xff09;前言 本文内容对应的是书本第 7 章的内容&am…...

贪心算法-蓝桥杯

一、贪心算法的优缺点优点&#xff1a;1.容易理解:生活常见。2.操作简单:在每一步都选局部最优。3.效率高: 复杂度常常是O(1)的。缺点&#xff1a;1.局部最优不一定是全局最优。二、例子: 最少硬币问题硬币面值1、2、5。支付13元&#xff0c;要求硬币数量最少。贪心法: (1) 5元…...

zookeeper 复习 ---- chapter03

zookeeper 复习 ---- chapter03如何创建 zookeeper 对象 要求&#xff1a; 1&#xff1a;知道这几个构造参数 2&#xff1a;知道每一个参数的含义 ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) ZooKeeper(String connectString, int sessionTimeout…...

1.PostgreSQL

文章目录LIMITWITH 和RECURSIVEPostgreSQL 约束PostgreSQL AUTO INCREMENT&#xff08;自动增长&#xff09;PostgreSQL PRIVILEGES&#xff08;权限&#xff09;GRANT语法LIMIT SELECT * FROM COMPANY LIMIT 3 OFFSET 2;WITH 和RECURSIVE WITH RECURSIVE t(a,b) AS (VALUES (…...

buu [UTCTF2020]basic-crypto 1

题目描述&#xff1a; 01010101 01101000 00101101 01101111 01101000 00101100 00100000 01101100 01101111 01101111 01101011 01110011 00100000 01101100 01101001 01101011 01100101 00100000 01110111 01100101 00100000 01101000 01100001 01110110 01100101 00100000 0…...

火山引擎数智平台的这款产品,正在帮助 APP 提升用户活跃度

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 你有没有关注过 APP 给你推送的消息&#xff1f; 出于提升用户活跃度的考虑&#xff0c;APP 会定期在应用内面向用户进行内通推送&#xff0c;推送形式既包括 APP …...

做网站电话/百度关键词排名突然没了

之前我一直用Seconds_behind_master来衡量主从的延迟&#xff0c;今天看到文档&#xff0c;才觉得多么不可靠&#xff01;以下是官方文档的描述&#xff1a; In essence, this field measures the time difference in seconds between the slave SQL thread and the slave I/O …...

深圳做网站龙华新科/百度关键词查询

一、日常关注的问题1、我们的日志生成速度&#xff1f;1、每天生成多少日志、产生多少redo logmysql> show global status like Innodb_os_log_written;-------------------------------| Variable_name | Value |-------------------------------| Innodb_os_log_written |…...

清河做网站哪家好/宁波seo免费优化软件

目录 作用安装全局配置配置进程池参考Company开发环境转发请求给PHP-FPM思考作用 PHP-FPM(PHP FastCGI Process Manager)意&#xff1a;PHP FastCGI 进程管理器&#xff0c;用于管理PHP 进程池的软件&#xff0c;用于接受web服务器的请求。 PHP-FPM提供了更好的PHP进程管理方式…...

长春市做网站哪家好/贵港seo

ORM的单表操作 MTV框架包含一个重要的部分就是ORM————对象关系映射&#xff08;Object Relational Mapping&#xff09;&#xff0c;它实现了数据模型与数据库的解耦&#xff0c;即数据模型的设计。利用它我们不需要依赖于特定的数据库&#xff0c;通过简单的配置就可以轻松…...

手机微信官方网站首页/seo如何提高排名

c语言输入姓名输出姓和名Input means to provide the program with some data to be used in the program and Output means to display data on screen or write the data to a printer or a file. 输入装置为程序提供一些要在程序中使用的数据&#xff0c; 输出装置为在屏幕上…...

wordpress英文网赚站/北京seo公司wyhseo

文章目录写在开头的话ZStack产品与解决方案介绍00. Zstack 愿景0.1 云计算在企业应用中的价值与意义0.2 企业建设云平台过程中的典型问题0.3 Zstack愿景01. 解决方案1.1 ZStack 产品图谱1.2 ZStack云平台1.3 ZStack 云平台应用场景1.4 ZStack Mini一体机1.5 ZStack Mini 适用场…...