为何segments与height变量无法影响绘制的Circle?如何实现填充?
问题解决方案
修复问题1:segments和height变量不生效
问题根源
CreatePoints方法中声明了局部变量var segments = 360;,直接覆盖了类的公共segments字段,导致外部修改无法传递到生成逻辑中。- 生成圆形顶点时,Y坐标硬编码为
0,未使用公共height字段,导致高度调整无效果。
修复动作
- 删除局部
segments变量,直接使用类的segments字段参与计算。 - 将顶点的Y坐标替换为
height字段值,让高度调整生效。
实现需求2:添加填充状态切换
实现思路
LineRenderer仅支持绘制线条,无法直接生成填充图形,因此通过MeshFilter+MeshRenderer生成三角形网格实现填充效果:
- 新增
isFilled布尔变量作为填充状态开关。 - 编写
GenerateFilledMesh方法生成三角形扇形网格(中心点+边缘点构成的三角面)。 - 根据
isFilled值切换LineRenderer(轮廓模式)和MeshRenderer(填充模式)的显示状态。
完整修正代码
using UnityEngine; using System.Collections.Generic; [ExecuteAlways] [RequireComponent(typeof(LineRenderer))] public class DrawTest : MonoBehaviour { [Range(1, 50)] public int segments = 50; [Range(1, 500)] public float xRadius = 5; [Range(1, 500)] public float yRadius = 5; [Range(0.1f, 5)] public float width = 0.1f; [Range(0, 100)] public float height = 0; public bool controlBothXradiusYradius = false; public bool draw = true; public bool isFilled = false; // 新增填充状态开关 [SerializeField] private LayerMask targetLayers; [SerializeField] private LineRenderer line; [SerializeField] private MeshFilter meshFilter; [SerializeField] private MeshRenderer meshRenderer; private void Start() { InitializeComponents(); if (draw) UpdateCircle(); } private void Update() { if (Physics.CheckSphere(transform.position, xRadius, targetLayers)) { Debug.Log("player detected"); } else { Debug.Log("player NOT detected"); } } private void InitializeComponents() { if (!line) line = GetComponent<LineRenderer>(); if (!meshFilter) meshFilter = GetComponent<MeshFilter>(); if (!meshRenderer) meshRenderer = GetComponent<MeshRenderer>(); // 自动添加缺失的网格组件 if (!meshFilter) meshFilter = gameObject.AddComponent<MeshFilter>(); if (!meshRenderer) meshRenderer = gameObject.AddComponent<MeshRenderer>(); // 给填充网格分配默认材质 if (meshRenderer && meshRenderer.sharedMaterial == null) { meshRenderer.sharedMaterial = new Material(Shader.Find("Standard")); } } public void UpdateCircle() { if (isFilled) { // 启用填充网格,禁用线条渲染 line.enabled = false; meshFilter.gameObject.SetActive(true); meshRenderer.gameObject.SetActive(true); GenerateFilledMesh(); } else { // 启用线条渲染,禁用填充网格 line.enabled = true; meshFilter.gameObject.SetActive(false); meshRenderer.gameObject.SetActive(false); line.useWorldSpace = false; line.startWidth = width; line.endWidth = width; line.positionCount = segments + 1; Vector3[] points = new Vector3[segments + 1]; for (int i = 0; i < segments + 1; i++) { float rad = Mathf.Deg2Rad * (i * 360f / segments); points[i] = new Vector3(Mathf.Sin(rad) * xRadius, height, Mathf.Cos(rad) * yRadius); } line.SetPositions(points); } } private void GenerateFilledMesh() { Mesh mesh = new Mesh(); List<Vector3> vertices = new List<Vector3>(); List<int> triangles = new List<int>(); // 添加中心点 vertices.Add(new Vector3(0, height, 0)); // 添加圆形边缘点 for (int i = 0; i < segments; i++) { float rad = Mathf.Deg2Rad * (i * 360f / segments); vertices.Add(new Vector3(Mathf.Sin(rad) * xRadius, height, Mathf.Cos(rad) * yRadius)); } // 重复第一个边缘点以闭合网格 vertices.Add(vertices[1]); // 生成三角形扇形索引 for (int i = 1; i <= segments; i++) { triangles.Add(0); triangles.Add(i); triangles.Add(i + 1); } mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.RecalculateNormals(); mesh.RecalculateBounds(); meshFilter.mesh = mesh; } #if UNITY_EDITOR private float prevXRadius, prevYRadius; private int prevSegments; private float prevWidth; private float prevHeight; private bool prevIsFilled; private void OnValidate() { InitializeComponents(); if (!line || !meshFilter || !meshRenderer) return; if (!draw) { // 禁用所有渲染组件 line.enabled = false; meshFilter.gameObject.SetActive(false); meshRenderer.gameObject.SetActive(false); return; } // 根据填充状态切换组件激活状态 if (isFilled) { line.enabled = false; meshFilter.gameObject.SetActive(true); meshRenderer.gameObject.SetActive(true); } else { line.enabled = true; meshFilter.gameObject.SetActive(false); meshRenderer.gameObject.SetActive(false); } // 检查参数变化并更新圆形 if (xRadius != prevXRadius || yRadius != prevYRadius || segments != prevSegments || width != prevWidth || height != prevHeight || isFilled != prevIsFilled) { UpdateCircle(); // 更新缓存值 prevXRadius = xRadius; prevYRadius = yRadius; prevSegments = segments; prevWidth = width; prevHeight = height; prevIsFilled = isFilled; } // 同步XY半径 if (controlBothXradiusYradius) { yRadius = xRadius; UpdateCircle(); prevYRadius = yRadius; } } #endif }
使用说明
- segments变量:调整圆形平滑度,数值越高圆形边缘越细腻。
- height变量:控制圆形在Y轴上的悬浮高度。
- isFilled变量:勾选后切换为填充模式,取消勾选恢复轮廓模式。
- 填充模式下可通过MeshRenderer的材质调整填充颜色、光照等视觉效果。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

