You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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
}

使用说明

  1. segments变量:调整圆形平滑度,数值越高圆形边缘越细腻。
  2. height变量:控制圆形在Y轴上的悬浮高度。
  3. isFilled变量:勾选后切换为填充模式,取消勾选恢复轮廓模式。
  4. 填充模式下可通过MeshRenderer的材质调整填充颜色、光照等视觉效果。

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:15:57