如何使用LineRenderer绘制一个圆形并将其作为子对象附着在目标物体周围?

3
当我将此脚本附加到对象上时,它会在周围绘制一个圆。现在,我想让脚本的线渲染器附加到一个空游戏对象上,该游戏对象将是绘制圆形的对象的子级。
我希望这样做是为了能够拖动空游戏对象并更改圆的高度。这样我就可以简单地复制空游戏对象并有两个圆,一个在地面上,一个在较高位置。两个圆都将以相同的半径围绕父对象,而父对象将成为中心。
using UnityEngine;
using System.Collections;
using System;

[ExecuteAlways]
[RequireComponent(typeof(LineRenderer))]
public class DrawRadiusAroundTurret : MonoBehaviour
{
    [Range(1, 50)] public int segments = 50;
    [Range(1, 5)] public float xRadius = 5;
    [Range(1, 5)] public float yRadius = 5;
    [Range(0.1f, 5f)] public float width = 0.1f;
    public bool controlBothXradiusYradius = false;
    public bool draw = true;

    [SerializeField] private LineRenderer line;

    private void Start()
    {
        if (!line) line = GetComponent<LineRenderer>();

        CreatePoints();
    }

    public void CreatePoints()
    {
        line.enabled = true;
        line.widthMultiplier = width;
        line.useWorldSpace = false;
        line.widthMultiplier = width;
        line.positionCount = segments + 1;

        float x;
        float y;

        var angle = 20f;
        var points = new Vector3[segments + 1];
        for (int i = 0; i < segments + 1; i++)
        {
            x = Mathf.Sin(Mathf.Deg2Rad * angle) * xRadius;
            y = Mathf.Cos(Mathf.Deg2Rad * angle) * yRadius;

            points[i] = new Vector3(x, 0f, y);

            angle += (380f / segments);
        }

        // it's way more efficient to do this in one go!
        line.SetPositions(points);
    }

#if UNITY_EDITOR
    private float prevXRadius, prevYRadius;
    private int prevSegments;
    private float prevWidth;

    private void OnValidate()
    {
        // Can't set up our line if the user hasn't connected it yet.
        if (!line) line = GetComponent<LineRenderer>();
        if (!line) return;

        if (!draw)
        {
            // instead simply disable the component
            line.enabled = false;
        }
        else
        {
            // Otherwise re-enable the component
            // This will simply re-use the previously created points
            line.enabled = true;

            if (xRadius != prevXRadius || yRadius != prevYRadius || segments != prevSegments || width != prevWidth)
            {
                CreatePoints();

                // Cache our most recently used values.
                prevXRadius = xRadius;
                prevYRadius = yRadius;
                prevSegments = segments;
                prevWidth = width;
            }

            if (controlBothXradiusYradius)
            {
                yRadius = xRadius;
            }
        }
    }
#endif
}

这里有一个问题,线渲染器和脚本都附加在导弹炮塔上,我想让它们附加在导弹炮塔的空游戏对象子级上,并且它将继续在导弹炮塔周围绘制相同的圆圈,但当它来自子对象时,我将能够更改圆圈的高度。

主要目标是在导弹炮塔周围拥有多个圆圈,但我可以通过简单拖动来更改圆圈的高度。


1
考虑添加一个可点击的“手柄”对象,可以在场景视图中拖动。当它移动时,更新圆的半径并重新计算点。创建一个带有圆形纹理的纹理四边形可能比使用LineRenderer或甚至是环面更有效,因为它们将遵守transform层次结构。 - 3Dave
1
通过为炮塔添加两个子对象,并在两者上都添加LineRenderer和脚本,将这个问题解决了。现在两个对象的位置都设置为0,0,0,它可以正常工作了。 - Benzi Avrumi
1
好的。那么当专利对象移动时,这是跟随它移动的吗?上次我使用LineRenderer时,它与.transform不兼容。 - 3Dave
1
@3Dave,你说得对。现在当移动父级时,它将与两个圆一起移动,而且您可以单独移动每个圆。这里是一个截图展示它。我称第一个圆为底部圆,在大多数情况下,我不会改变它的位置。第二个子元素是移动圆,这个我将更改它的高度。https://imgur.com/a/9Pv97RZ - Benzi Avrumi
1
很好。我建议将其发布为答案,并包括任何更新的代码。这可能对未来的其他人有所帮助。 - 3Dave
1个回答

0
解决方案是创建空的游戏对象作为子对象,每个子对象的位置设置为0,0,0。然后向每个子对象添加一个线渲染组件和脚本。
脚本:
using UnityEngine;
using System.Collections;
using System;

[ExecuteAlways]
[RequireComponent(typeof(LineRenderer))]
public class DrawRadiusAroundTurret : MonoBehaviour
{
    [Range(1, 50)] public int segments = 50;
    [Range(1, 5)] public float xRadius = 5;
    [Range(1, 5)] public float yRadius = 5;
    [Range(0.1f, 5f)] public float width = 0.1f;
    public bool controlBothXradiusYradius = false;
    public bool draw = true;

    [SerializeField] private LineRenderer line;

    private void Start()
    {
        if (!line) line = GetComponent<LineRenderer>();

        CreatePoints();
    }

    //private void Update()
    //{
    //    
    //}

    public void CreatePoints()
    {
        line.enabled = true;
        line.widthMultiplier = width;
        line.useWorldSpace = false;
        line.widthMultiplier = width;
        line.positionCount = segments + 1;

        float x;
        float y;

        var angle = 20f;
        var points = new Vector3[segments + 1];
        for (int i = 0; i < segments + 1; i++)
        {
            x = Mathf.Sin(Mathf.Deg2Rad * angle) * xRadius;
            y = Mathf.Cos(Mathf.Deg2Rad * angle) * yRadius;

            points[i] = new Vector3(x, 0f, y);

            angle += (380f / segments);
        }

        // it's way more efficient to do this in one go!
        line.SetPositions(points);
    }

#if UNITY_EDITOR
    private float prevXRadius, prevYRadius;
    private int prevSegments;
    private float prevWidth;

    private void OnValidate()
    {
        // Can't set up our line if the user hasn't connected it yet.
        if (!line) line = GetComponent<LineRenderer>();
        if (!line) return;

        if (!draw)
        {
            // instead simply disable the component
            line.enabled = false;
        }
        else
        {
            // Otherwise re-enable the component
            // This will simply re-use the previously created points
            line.enabled = true;

            if (xRadius != prevXRadius || yRadius != prevYRadius || segments != prevSegments || width != prevWidth)
            {
                CreatePoints();

                // Cache our most recently used values.
                prevXRadius = xRadius;
                prevYRadius = yRadius;
                prevSegments = segments;
                prevWidth = width;
            }

            if (controlBothXradiusYradius)
            {
                yRadius = xRadius;
            }
        }
    }
#endif
}

截图:

Circles


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接