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

unity 做一个圆形分比图

// 在其他脚本中控制多段进度
using System.Collections.Generic;
using UnityEngine;public class GameManager : MonoBehaviour
{public MultiCircleProgress circleProgress;void Start(){// 初始化数据circleProgress.segments = new List<MultiCircleProgress.ProgressSegment>{new MultiCircleProgress.ProgressSegment{name = "",progress = 0.2f,color = Color.red},new MultiCircleProgress.ProgressSegment{name = "",progress = 0.3f,color = Color.blue},new MultiCircleProgress.ProgressSegment{name = "",progress = 0.3f,color = Color.green},new MultiCircleProgress.ProgressSegment{name = "",progress = 0.1f,color = Color.black},new MultiCircleProgress.ProgressSegment{name = "",progress = 0.1f,color = Color.cyan}};circleProgress.CreateSegments();}void UpdatePlayerStats(float health, float mana, float stamina){circleProgress.UpdateSegment(0, health);circleProgress.UpdateSegment(1, mana);circleProgress.UpdateSegment(2, stamina);}
}```
脚本挂到场景中一个模型上,脚本可以设置生成得比例```csharp
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;public class MultiCircleProgress : MonoBehaviour
{[System.Serializable]public class ProgressSegment{public string name;[Range(0, 1)] public float progress;public Color color;[HideInInspector] public Image fillImage;[HideInInspector] public Text textComponent;}[Header("UI Elements")]public List<ProgressSegment> segments = new List<ProgressSegment>();public GameObject segmentPrefab;public Text percentTextTemplate;public Transform textContainer;[Header("Text Positioning")]public float textDistanceFromCenter = 0.7f; // 基于半径的比例 (0.5=边缘, 1.0=两倍半径)public float textOffsetAngle = 0f;public float textMinDistance = 30f;public float textMaxDistance = 200f;private RectTransform baseRectTransform;private float baseRadius;void Start(){InitializeComponents();CreateSegments();}void InitializeComponents(){baseRectTransform = GetComponent<RectTransform>();baseRadius = Mathf.Min(baseRectTransform.rect.width, baseRectTransform.rect.height) / 2f;}public void CreateSegments(){ClearExistingSegments();ClearExistingTexts();float currentRotation = 0f;for (int i = 0; i < segments.Count; i++){CreateSegment(i, ref currentRotation);}}void ClearExistingSegments(){foreach (Transform child in transform){if (child != textContainer) Destroy(child.gameObject);}}void ClearExistingTexts(){if (textContainer != null){foreach (Transform child in textContainer){Destroy(child.gameObject);}}}void CreateSegment(int index, ref float currentRotation){// 创建进度段GameObject segmentObj = Instantiate(segmentPrefab, transform);segments[index].fillImage = segmentObj.GetComponent<Image>();// 配置段属性ConfigureSegment(index, currentRotation);// 创建并定位文本if (percentTextTemplate != null && textContainer != null){CreateSegmentText(index, currentRotation);}currentRotation += segments[index].progress * 360f;}void ConfigureSegment(int index, float rotation){segments[index].fillImage.color = segments[index].color;segments[index].fillImage.type = Image.Type.Filled;segments[index].fillImage.fillMethod = Image.FillMethod.Radial360;segments[index].fillImage.fillOrigin = (int)Image.Origin360.Top;segments[index].fillImage.fillClockwise = true;segments[index].fillImage.transform.rotation = Quaternion.Euler(0, 0, -rotation);segments[index].fillImage.fillAmount = segments[index].progress;}void CreateSegmentText(int index, float segmentStartRotation){Text textObj = Instantiate(percentTextTemplate, textContainer);textObj.gameObject.SetActive(true);segments[index].textComponent = textObj;textObj.text = $"{segments[index].name} {Mathf.RoundToInt(segments[index].progress * 100)}%";textObj.color = segments[index].color;PositionTextOutsideCircle(index, segmentStartRotation);}void PositionTextOutsideCircle(int index, float segmentStartRotation){if (segments[index].textComponent == null) return;// 计算当前半径float currentRadius = Mathf.Min(Mathf.Max(baseRectTransform.rect.width, baseRectTransform.rect.height) / 2f,textMaxDistance);// 计算有效文本距离 (基于比例但限制在最小/最大值之间)float effectiveTextDistance = Mathf.Max(currentRadius * textDistanceFromCenter,textMinDistance);// 计算扇形中心角度float midAngle = segmentStartRotation + (segments[index].progress * 180f) + textOffsetAngle;// 计算文本位置 (圆形中心向外延伸)Vector3 textDirection = Quaternion.Euler(0, 0, -midAngle) * Vector3.up;segments[index].textComponent.rectTransform.anchoredPosition = textDirection * effectiveTextDistance;// 保持文本水平segments[index].textComponent.rectTransform.localRotation = Quaternion.identity;// 设置文本锚点为中心,方便定位segments[index].textComponent.rectTransform.anchorMin =segments[index].textComponent.rectTransform.anchorMax =segments[index].textComponent.rectTransform.pivot = new Vector2(0.5f, 0.5f);}public void UpdateAllProgress(){float currentRotation = 0f;for (int i = 0; i < segments.Count; i++){segments[i].progress = Mathf.Clamp01(segments[i].progress);// 更新填充和旋转if (segments[i].fillImage != null){segments[i].fillImage.transform.rotation = Quaternion.Euler(0, 0, -currentRotation);segments[i].fillImage.fillAmount = segments[i].progress;}// 更新文本if (segments[i].textComponent != null){segments[i].textComponent.text = $"{segments[i].name}: {Mathf.RoundToInt(segments[i].progress * 100)}%";PositionTextOutsideCircle(i, currentRotation);}currentRotation += segments[i].progress * 360f;}}public void UpdateSegment(int index, float progress){if (index >= 0 && index < segments.Count){segments[index].progress = Mathf.Clamp01(progress);UpdateAllProgress();}}#if UNITY_EDITORvoid OnValidate(){if (baseRectTransform == null)baseRectTransform = GetComponent<RectTransform>();if (!Application.isPlaying && baseRectTransform != null){UnityEditor.EditorApplication.delayCall += () => {if (this != null) UpdateAllProgress();};}}
#endif
}

创建UI结构:

创建 Canvas

在 Canvas 下创建空对象 “MultiProgress”

创建空对象 “TextContainer” 作为文本父对象

准备预制体:

创建 Image 对象,命名为 “SegmentPrefab”

设置为 Filled 类型,Fill Method 为 Radial 360

将其做成预制体

准备文本模板:

创建 Text 对象,设置好字体样式

初始设置为非激活状态

命名为 “PercentTextTemplate”

添加组件:

给 “MultiProgress” 对象添加 MultiCircleProgress 脚本

将预制体和文本模板拖拽到脚本对应字段

在 Inspector 中添加和配置各个段


http://www.mrgr.cn/news/96159.html

相关文章:

  • #C8# UVM中的factory机制 #S8.5# 对factory机制的重载进一步思考
  • 第十四届蓝桥杯省赛电子类单片机学习记录(客观题)
  • UDP视频传输中的丢包和播放花屏处理方法
  • Linux一步部署主DNS服务器
  • RGB-T综述
  • FALL靶场通关攻略
  • 【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解
  • Springbean(二)@Component及其派生注解自动注入(2)使用注意和加载问题
  • HarmonyOS之深入解析跳转支付宝小程序完成操作后如何自动返回App
  • 设计秒杀系统(高并发的分布式系统)
  • node-ddk,electron,主进程通讯,窗口间通讯
  • 为AI聊天工具添加一个知识系统 之152 当今AI模型和AI工具应用中的核心矛盾
  • cesium中label样式修改为圆角
  • Ubuntu24.04 离线安装 MySQL8.0.41
  • 软考《信息系统运行管理员》- 5.3 信息系统数据资源备份
  • 在Cesium中创建渐变色墙体效果
  • [二值图像处理] 骨架线提取、骨架端点、交叉点提取
  • Ollama未授权访问
  • 力扣:回溯算法
  • AS400==WINDOWS开发COBOL/安装DB2/连接DB2