c# - 在 Unity 中创建 2D 圆形网格

标签 c# unity-game-engine mesh

我目前有一个“CreateMesh”脚本,可以将其作为具有网格渲染器和网格过滤器的对象的组件,并且使用多边形碰撞器在网格尺寸中创建一个 2D 网格,给定“MeshType”变量设置为“tri”或“box”(分别用于三角形和矩形网格。)我还想添加创建圆形网格的功能,但是从一些研究中我意识到这并不那么简单正如我首先想到的。然而我还没有找到任何有帮助的东西。

这是我用于盒子和三角形网格的代码:

public float width = 5f;
public float height = 5f;

public string meshType;

public PolygonCollider2D polyCollider;

void Start()
{
    polyCollider = GetComponent<PolygonCollider2D>();
}

// Update is called once per frame
void Update () {
    if (meshType == "tri")
    {
        TriangleMesh(width, height);
    }
    if (meshType == "box")
    {
        BoxMesh(width, height);
    }

}

void TriangleMesh(float width, float height)
{
    MeshFilter mf = GetComponent<MeshFilter>();
    Mesh mesh = new Mesh();
    mf.mesh = mesh;

    //Verticies
    Vector3[] verticies = new Vector3[3]
    {
        new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0, height, 0)
    };

    //Triangles
    int[] tri = new int[3];

    tri[0] = 0;
    tri[1] = 2;
    tri[2] = 1;

    //normals
    Vector3[] normals = new Vector3[3];

    normals[0] = -Vector3.forward;
    normals[1] = -Vector3.forward;
    normals[2] = -Vector3.forward;

    //UVs
    Vector2[] uv = new Vector2[3];

    uv[0] = new Vector2(0, 0);
    uv[0] = new Vector2(1, 0);
    uv[0] = new Vector2(0, 1);

    //initialise
    mesh.vertices = verticies;
    mesh.triangles = tri;
    mesh.normals = normals;
    mesh.uv = uv;

    //setting up collider
    polyCollider.pathCount = 1;

    Vector2[] path = new Vector2[3]
    {
        new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
    };

    polyCollider.SetPath(0, path);

}

void BoxMesh(float width, float height)
{
    MeshFilter mf = GetComponent<MeshFilter>();
    Mesh mesh = new Mesh();
    mf.mesh = mesh;

    //Verticies
    Vector3[] verticies = new Vector3[4]
    {
        new Vector3(0,0,0), new Vector3(0, height, 0), new Vector3(width, height, 0), new Vector3(width, 0, 0)
    };

    //Triangles
    int[] tri = new int[6];

    tri[0] = 0;
    tri[1] = 1;
    tri[2] = 3;

    tri[3] = 1;
    tri[4] = 2;
    tri[5] = 3;

    //normals
    Vector3[] normals = new Vector3[4];

    normals[0] = -Vector3.forward;
    normals[1] = -Vector3.forward;
    normals[2] = -Vector3.forward;
    normals[3] = -Vector3.forward;

    //UVs
    Vector2[] uv = new Vector2[4];

    uv[0] = new Vector2(0, 0);
    uv[1] = new Vector2(0, 1);
    uv[2] = new Vector2(1, 1);
    uv[3] = new Vector2(1, 0);

    //initialise
    mesh.vertices = verticies;
    mesh.triangles = tri;
    mesh.normals = normals;
    mesh.uv = uv;

    //setting up collider
    polyCollider.pathCount = 1;

    Vector2[] path = new Vector2[4]
    {
        new Vector2(0,0), new Vector2(0, height), new Vector2(width, height), new Vector2(width, 0)
    };

    polyCollider.SetPath(0, path);

}

所以本质上我想要一个可以在更新方法中调用的函数,它可以简单地创建一个圆形网格。例如:

void Update () {
   if (meshType == "tri")
   {
       TriangleMesh(width, height);
   }
   if (meshType == "box")
   {
       BoxMesh(width, height);
   }
   if (meshType == "circle")
   {
       CircleMesh(radius);
   }
}

最佳答案

我设法找到的解决方案涉及创建一个 n 边且 n 值较大的正多边形。我有一个名为 PolyMesh 的函数,它创建一个具有 n 条边和给定半径的正多边形网格。

生成顶点

对于 n 边正多边形的每个顶点,相对于多边形中心的坐标由以下公式给出:x = r*i*sin(θ)y = r* i*cos(θ) 因此,x = r*i*sin(2π/2)y = r*i*cos(2π/2) >。其中 i 从 0 迭代到 n-1。因此,我们可以拥有一个分配有顶点的列表,然后将其转换为数组:

    //verticies
    List<Vector3> verticiesList = new List<Vector3> { };
    float x;
    float y;
    for (int i = 0; i < n; i ++)
    {
        x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
        y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
        verticiesList.Add(new Vector3(x, y, 0f));
    }
    Vector3[] verticies = verticiesList.ToArray();

生成三角形

给定的 n 边正多边形可以从同一点分割成 n-2 个三角形。所以我们可以如下生成每个三角形:

    //triangles
    List<int> trianglesList = new List<int> { };
    for(int i = 0; i < (n-2); i++)
    {
        trianglesList.Add(0);
        trianglesList.Add(i+1);
        trianglesList.Add(i+2);
    }
    int[] triangles = trianglesList.ToArray();

生成法线

由于这是一个 2d 对象,我们可以将每个法线设置为 -Vector3.forward,如下所示:

    //normals
    List<Vector3> normalsList = new List<Vector3> { };
    for (int i = 0; i < verticies.Length; i++)
    {
        normalsList.Add(-Vector3.forward);
    }
    Vector3[] normals = normalsList.ToArray();

生成碰撞器

我们可以只使用具有相同半径的圆形碰撞器,但为了使该函数适用于 n 值较小的多边形,我们必须使用 PolygonCollider2D。由于顶点已经在顶点数组中按顺序排列,我们可以简单地将它们用作 PolygonCollider2D 的路径。

    //polyCollider
    polyCollider.pathCount = 1;

    List<Vector2> pathList = new List<Vector2> { };
    for (int i = 0; i < n; i++)
    {
        pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
    }
    Vector2[] path = pathList.ToArray();

    polyCollider.SetPath(0, path);

完整的代码应如下所示:

public PolygonCollider2D polyCollider;

void Start()
{
    polyCollider = GetComponent<PolygonCollider2D>();
}

void PolyMesh(float radius, int n)
{
    MeshFilter mf = GetComponent<MeshFilter>();
    Mesh mesh = new Mesh();
    mf.mesh = mesh;

    //verticies
    List<Vector3> verticiesList = new List<Vector3> { };
    float x;
    float y;
    for (int i = 0; i < n; i ++)
    {
        x = radius * Mathf.Sin((2 * Mathf.PI * i) / n);
        y = radius * Mathf.Cos((2 * Mathf.PI * i) / n);
        verticiesList.Add(new Vector3(x, y, 0f));
    }
    Vector3[] verticies = verticiesList.ToArray();

    //triangles
    List<int> trianglesList = new List<int> { };
    for(int i = 0; i < (n-2); i++)
    {
        trianglesList.Add(0);
        trianglesList.Add(i+1);
        trianglesList.Add(i+2);
    }
    int[] triangles = trianglesList.ToArray();

    //normals
    List<Vector3> normalsList = new List<Vector3> { };
    for (int i = 0; i < verticies.Length; i++)
    {
        normalsList.Add(-Vector3.forward);
    }
    Vector3[] normals = normalsList.ToArray();

    //initialise
    mesh.vertices = verticies;
    mesh.triangles = triangles;
    mesh.normals = normals;

    //polyCollider
    polyCollider.pathCount = 1;

    List<Vector2> pathList = new List<Vector2> { };
    for (int i = 0; i < n; i++)
    {
        pathList.Add(new Vector2(verticies[i].x, verticies[i].y));
    }
    Vector2[] path = pathList.ToArray();

    polyCollider.SetPath(0, path);
}

An introduction to meshes

关于c# - 在 Unity 中创建 2D 圆形网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50606756/

相关文章:

unity-game-engine - 如何将 ZWrite channel 添加到透明着色器图表?

c++ - 为什么这个三角形重新排序算法会导致随机连接?

c# - 如何通过脚本统一制作多个网格?

c# - C#、SQL 2005、VS 2008 中的 "Object reference not set to an instance of an object."

animation - Unity动画循环偏移不起作用

c# - Visual Studio 2017 禁用文件夹命名空间

ios - 使用 iOS 版 GoogleVR (GoogleCardboard) 在 Unity 中创建单一 View

python - Meshgrid 等值线图的不一致数据集

c# - 什么时候使用方法而不是属性来定义类?

c# - 如何从json格式中删除 ""