如何在Unity 3D中绘制球体表面的纬度/经度线?

时间:2018-01-16 09:58:33

标签: c# unity3d

我是Unity 3D的初学者。我正在尝试使用Unity 3D创建一个地球仪,如下所示。我在场景上创建了一个Sphere游戏对象并将半径设置为640.然后,我想在C#脚本中在此Sphere的表面上绘制纬度/经度线(每10度)。

enter image description here

我尝试使用LineRender绘制每条纬线/长线,但没有让它工作。 我的代码:

public class EarthController : MonoBehaviour {
private float _radius = 0;
// Use this for initialization
void Start () {
    _radius = gameObject.transform.localScale.x;
    DrawLatLongLines();
}

// Update is called once per frame
void Update()
{
}

private void DrawLatLongLines()
{
    float thetaStep = 0.0001F;
    int size = (int)((2.0 * Mathf.PI) / thetaStep); 

    // draw lat lines
    for (int latDeg = 0; latDeg < 90; latDeg += 10)
    {
        // throw error here. 
        // seems I cannot add more than one component per type
        LineRenderer latLineNorth = gameObject.AddComponent<LineRenderer>(); 
        latLineNorth.startColor = new Color(255, 0, 0);
        latLineNorth.endColor = latLineNorth.startColor;
        latLineNorth.startWidth = 0.2F;
        latLineNorth.endWidth = 0.2F;
        latLineNorth.positionCount = size;

        LineRenderer latLineSouth = Object.Instantiate<LineRenderer>(latLineNorth);

        float theta = 0;
        var r = _radius * Mathf.Cos(Mathf.Deg2Rad * latDeg);
        var z = _radius * Mathf.Sin(Mathf.Deg2Rad * latDeg);
        for (int i = 0; i < size; i++)
        {
            var x = r * Mathf.Sin(theta);
            var y = r * Mathf.Cos(theta);

            Vector3 pos = new Vector3(x, y, z);
            latLineNorth.SetPosition(i, pos);

            pos.z = -z;
            latLineSouth.SetPosition(i, pos);

            theta += thetaStep;
        }
    }
}
}

这样做的正确方法是什么?

我不想编写自定义着色器(如果可能),因为我一无所知。

1 个答案:

答案 0 :(得分:1)

自定义3d对象外观的常用方法是使用着色器。

在您的情况下,您需要一个线框着色器,如果您想控制线数,那么您可能需要自己编写。

另一种解决方案是使用纹理。在统一中,您将拥有许多将在对象上应用纹理的默认材质。您可以应用包含线条的图像纹理。

如果您不想要纹理而只想要线条,则可以使用线条渲染器。 LineRenderer不需要3D对象来工作。你只要给它一些点,它就会用一条线将它们联系起来。 我将如何做到这一点:

  • 使用线条渲染器创建对象并输入创建的线条 circle(您可以在c#中动态执行或在编辑器中手动执行 线渲染器。)。
  • 将其存储为预制件(可选)并将其复制到场景中 (复制粘贴。每个副本绘制一个新行
  • 只需修改线条的旋转,缩放和位置即可 可以重新创建一个球体

如果您的问题是&#34;圆的等式是什么,那么我可以找到正确的x和y坐标?&#34;这是一个计算x和y坐标的简短想法

for(int i =0; i< nbPointsOnTheCircle; ++i)
{
    var x = Mathf.Cos(nbPointsOnTheCircle / 360);
    var y = Mathf.Sin(nbPointsOnTheCircle / 360);
}

如果您的问题是&#34;如何使用Unity动态分配线条渲染器上的点?&#34;这是一个简短的例子:

public class Circle : MonoBehavior
{
    private void Start()
    {
        Vector3[] circlePoints = computePoints(); // a function that compute points of a circle
        var lineRenderer = GetComponent<LineRenderer>();
        linerenderer.Positions = circlePoints;
    }
}

修改

每个对象只能有一个。这就是为什么上面的示例仅绘制一个圈。你已经有一个地球控制器,但是这个控制器不能为自己添加许多LineRenderes。相反,我们的想法是地球对象有一个脚本可以执行以下操作:

private void Start()
{
    for(int i=0; i<nbLines;++i) 
    {
        GameObject go = new GameObject();
        go.AddComponent<LineRenderer>();
        go.AddCOmponent<Circle>();
        go.transform.SetParent = transform;
        go.name = "Circle" + i;
    }
}

然后你会看到在你的场景中创建了几个对象,每个对象只有一个LineRenderer和一个Circle组件

从那里你应该能够做你想做的事情(例如,将参数传递给Circle,这样每个圆圈都有点不同)