【问题标题】:How can I draw a circle in Unity3D?如何在 Unity3D 中画一个圆?
【发布时间】:2012-12-04 17:19:15
【问题描述】:

如何在 Unity 3d 中画圆? 我想在不同的物体周围画一个圆圈。 圆的半径不同,圆有纹理——正方形。

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    我发现这段代码有一个很大的错误。点数(大小)不应为“(2 * pi / theta_scale) + 1”,因为这会导致圆绘制 6.28 次。大小应为“1 / theta_scale + 1”。所以对于 0.01 的 theta_scale 需要绘制 100 个点,对于 0.1 的 theta_scale 需要绘制 10 个点。否则它将分别绘制 62 次和 628 次。 这是我使用的代码。

    using UnityEngine;
    using System.Collections;
    
    public class DrawRadar: MonoBehaviour {
        public float ThetaScale = 0.01 f;
        public float radius = 3 f;
        private int Size;
        private LineRenderer LineDrawer;
        private float Theta = 0 f;
    
        void Start() {
            LineDrawer = GetComponent < LineRenderer > ();
        }
    
        void Update() {
            Theta = 0 f;
            Size = (int)((1 f / ThetaScale) + 1 f);
            LineDrawer.SetVertexCount(Size);
            for (int i = 0; i < Size; i++) {
                Theta += (2.0 f * Mathf.PI * ThetaScale);
                float x = radius * Mathf.Cos(Theta);
                float y = radius * Mathf.Sin(Theta);
                LineDrawer.SetPosition(i, new Vector3(x, y, 0));
            }
        }
    }
    

    如果修改“Size”中除以ThetaScale的数字,就可以制作出扫尺/饼图类型的图形。

    【讨论】:

    • 这应该是正确的答案,因为@Jerdak 的代码画了很多不必要的行,但是这段代码只经过一次,并且一次画了每个角。不过,请注意,对于无孔线,您应该这样做:Size = (int)((1f / ThetaScale) + 2f)
    • SetVertexCount 现在已弃用。同样对于任何想知道他们的圈子在哪里的人,如果您没有关闭use world space,这会在世界原点创建一个垂直环。我为新版本的统一添加了答案。
    【解决方案2】:

    See Unity Answers 类似问题。

    Alternatively:

    float theta_scale = 0.1;  // Circle resolution
    
    LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
    lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
    lineRenderer.SetColors(c1, c2);
    lineRenderer.SetWidth(0.2F, 0.2F);
    lineRenderer.SetVertexCount(size);
    
    int i = 0;
    for(float theta = 0; theta < 2 * PI; theta += theta_scale) {
        x = r*cos(theta);
        y = r*sin(theta);
    
        Vector3 pos = new Vector3(x, y, 0);
        lineRenderer.SetPosition(i, pos);
        i+=1;
    }
    

    LineRenderer 需要连续点。您可以稍微修改此代码以使用圆柱体游戏对象而不是线渲染器。我发现 LineRenderer 有点可怕。

    最后,类似于第一个链接,您可以将圆形纹理附加到单位平面。使不属于圆形的纹理的任何部分透明。然后只需缩放并对齐平面以适合您的对象。不幸的是,如果有人看起来几乎平行于平面,这种方法就不是很好。

    【讨论】:

      【解决方案3】:

      Jerdak 的解决方案很好,但是代码很乱,所以我不得不稍微调整一下。这是一个类的代码,我在循环中使用 i 来避免错误。

      它还会用它的游戏对象位置更新圆的位置。

      using UnityEngine;
      using System.Collections;
      
      public class CircleDraw : MonoBehaviour {   
        float theta_scale = 0.01f;        //Set lower to add more points
        int size; //Total number of points in circle
        float radius = 3f;
        LineRenderer lineRenderer;
      
        void Awake () {       
          float sizeValue = (2.0f * Mathf.PI) / theta_scale; 
          size = (int)sizeValue;
          size++;
          lineRenderer = gameObject.AddComponent<LineRenderer>();
          lineRenderer.material = new Material(Shader.Find("Particles/Additive"));
          lineRenderer.SetWidth(0.02f, 0.02f); //thickness of line
          lineRenderer.SetVertexCount(size);      
        }
      
        void Update () {      
          Vector3 pos;
          float theta = 0f;
          for(int i = 0; i < size; i++){          
            theta += (2.0f * Mathf.PI * theta_scale);         
            float x = radius * Mathf.Cos(theta);
            float y = radius * Mathf.Sin(theta);          
            x += gameObject.transform.position.x;
            y += gameObject.transform.position.y;
            pos = new Vector3(x, y, 0);
            lineRenderer.SetPosition(i, pos);
          }
        }
      }
      

      【讨论】:

        【解决方案4】:

        使用 Shader Graph 我们现在可以绘制像素完美的圆。

        创建此图表后,基于此着色器创建新材质。

        然后用精灵渲染器创建一个新的游戏对象并设置你刚刚创建的材质。

        您可以使用材质的“缩放”参数来缩放圆。

        【讨论】:

        • 感谢您提供替代解决方案。作为一名程序员,我发现这是最有帮助的。
        【解决方案5】:

        最佳答案中的 linerenderer 方法非常简单,正是我想要的。我针对较新版本的 Unity 进行了更新,并进行了一些小调整以使其对初学者/用户更加友好。

        具体来说:

        • LineRenderer.SetVertexCount() 在较新版本的 Unity 中已弃用,替换为 positionCount
        • 将 theta 刻度替换为实际段数以消除猜测
        • 添加了循环设置 - 不确定这是否在旧版本的 Unity 中,可以在 LineRenderer 的检查器中设置
        • 删除了不必要的 Update 函数 - 渲染的线条是一个持久的游戏对象
        using UnityEngine;
        [RequireComponent(typeof(LineRenderer))]
        public class DrawRing : MonoBehaviour
        {
            public LineRenderer lineRenderer;
            [Range(6,60)]   //creates a slider - more than 60 is hard to notice
            public int lineCount;       //more lines = smoother ring
            public float radius;
            public float width;
        
            void Start()
            {
                lineRenderer = GetComponent<LineRenderer>();
                lineRenderer.loop = true;
                Draw();
            }
        
            void Draw() //Only need to draw when something changes
            {
                lineRenderer.positionCount = lineCount;
                lineRenderer.startWidth = width;
                float theta = (2f * Mathf.PI) / lineCount;  //find radians per segment
                float angle = 0;
                for (int i = 0; i < lineCount; i++)
                {
                    float x = radius * Mathf.Cos(angle);
                    float y = radius * Mathf.Sin(angle);
                    lineRenderer.SetPosition(i, new Vector3(x, 0, y));
                    //switch 0 and y for 2D games
                    angle += theta;
                }
            }
        }
        

        请注意,这假定附加到您想要环的游戏对象。所以LineRenderer 中的Use World Space 选项应该被取消选中。还要记住,游戏对象的比例会影响点的位置和线的宽度。

        把它放在地上(就像在一个单位选择圈里):

        1. 将脚本放在单独的游戏对象上
        2. 将游戏对象 X 旋转 90 度
        3. 检查 linerenderer 上的 use world space
        4. 将 linerenderer Alignment 设置为 Transform Z
        5. SetPosition 中将要圈出的事物的位置添加到xy。可能同时将 0 替换为 0.1fyOffset 变量以避免与地形发生 z-fighting。

        【讨论】:

          【解决方案6】:

          圆可以使用着色器绘制 - 如果它在半径上从中心绘制像素。

          【讨论】:

            【解决方案7】:

            使用 Sprite 执行以下操作。 Chan 在场景中飞行,所以她略高于飞机。我让她飞,所以我可以得到一个很好的截图,而不是因为它不能很好地与飞机配合。

            我使用了一个低分辨率的圆形精灵。 X 旋转 90 比例 X 15、Y 15、Z 1

            然后我设置排序层,所以它将呈现在默认层之上。当我遇到这篇文章时,我正在对此进行测试。它不能很好地处理阴影。我必须弄清楚绘制了哪些图层阴影以确保它们被渲染到精灵上。

            【讨论】:

              【解决方案8】:

              我有一个shader,我通常从它开始制作镜头光晕之类的效果,它会形成一个圆圈。使用着色器是最好的选择,因为你会得到完美的平滑和圆形。

              此外,由于着色器更改不需要重新编译和重新进入播放模式,因此很容易试验和调整着色器。

              【讨论】:

                【解决方案9】:

                我建议为 GameObject 创建扩展方法。对我很好。

                public static class GameObjectExtension
                {
                    const int numberOfSegments = 360;
                    public static void DrawCircle(this GameObject go, float radius, 
                float lineWidth, Color startColor, Color endColor, bool lineRendererExists=true)
                    {
                        LineRenderer circle = lineRendererExists ? go.GetComponent<LineRenderer>() : go.AddComponent<LineRenderer>();
                        circle.useWorldSpace = false;
                        circle.startWidth = lineWidth;
                        circle.endWidth = lineWidth;
                        circle.endColor = endColor;
                        circle.startColor = startColor;
                        circle.positionCount = numberOfSegments + 1;
                        Vector3 [] points = new Vector3[numberOfSegments + 1];
                
                        for (int i = 0; i < numberOfSegments + 1; i++)
                        {
                            float rad = Mathf.Deg2Rad * i;
                            points[i] = new Vector3(Mathf.Sin(rad) * radius, 0, Mathf.Cos(rad) * radius);
                        }
                        circle.SetPositions(points);
                    }
                }
                

                还有一点需要注意:如果没有应用LineRenderer 组件,最后一个参数必须是false

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-11-12
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多