【问题标题】:Submesh not appearing with different materials Unity2D使用不同的材质Unity2D没有出现子网格
【发布时间】:2018-11-30 01:50:14
【问题描述】:

我有一些代码可以创建一个圆形网格,它需要一个半径、多个边(一个圆选择为 100 左右)和一个轮廓宽度。它初始化网格如下:

MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;

mesh.subMeshCount = 2;

它用一些不完全自我解释的数学来分配顶点,但我想相信它会将顶点分配为具有 n 边的正多边形,然后再分配一个轮廓:

//vertices
List<Vector3> verticesList = 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);
    verticesList.Add(new Vector3(x, y, 0f));
}
for (int i = 0; i < n; i++)
{
    x = (radius + OLwidth) * Mathf.Sin((2 * Mathf.PI * i) / n);
    y = (radius + OLwidth) * Mathf.Cos((2 * Mathf.PI * i) / n);
    verticesList.Add(new Vector3(x, y, 0f));
}
Vector3[] vertices = verticesList.ToArray();

然后有两个三角形列表,mesh.SetTriangles() 稍后用这两个三角形数组制作两个子网格:

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

所有法线都只是-Vector3.forward

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

然后我初始化网格如下:

//initialise
mesh.vertices = vertices;
mesh.normals = normals;
mesh.SetTriangles(triangles, 0);
mesh.SetTriangles(OLtriangles, 1);

所以完整的代码如下所示(最后设置了一个 polycollider,但这与此无关):

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

    mesh.subMeshCount = 2;

    //vertices
    List<Vector3> verticesList = 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);
        verticesList.Add(new Vector3(x, y, 0f));
    }
    for (int i = 0; i < n; i++)
    {
        x = (radius + OLwidth) * Mathf.Sin((2 * Mathf.PI * i) / n);
        y = (radius + OLwidth) * Mathf.Cos((2 * Mathf.PI * i) / n);
        verticesList.Add(new Vector3(x, y, 0f));
    }
    Vector3[] vertices = verticesList.ToArray();

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

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

    //initialise
    mesh.vertices = vertices;
    mesh.normals = normals;
    mesh.SetTriangles(triangles, 0);
    mesh.SetTriangles(OLtriangles, 1);

    //polyCollider
    polyCollider.pathCount = 1;

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

    polyCollider.SetPath(0, path);
}

据我所知,这应该设置两个网格,一个比另一个稍大。这可行,但是尽管为网格渲染器分配了两种不同的材质,它们始终显示为相同的颜色。

这是网格在游戏中的显示方式:

这表明显然有两个网格:

我的Mesh Renderer如下:

这些是正在使用的材料:

我尝试在渲染器中简单地交换材质,但这只会使对象成为与其他材质的单一材质。

经过进一步的实验,我想澄清这不是由 Z-fighting 引起的,我通过更改轮廓的 z 坐标进行了实验,并实时更改了材质,无论我做什么,它们都具有相同的材质出于某种原因。

【问题讨论】:

    标签: c# unity3d mesh


    【解决方案1】:

    您的“轮廓”网格构造不正确。

    您的“轮廓”网格实际上是一个圆圈,而不是一个环。

    正因为如此,在渲染整个东西的时候,轮廓和内部在同一个地方。如果您要移动相机,我怀疑您会看到一些Z-Fighting

    要正确渲染您的对象,您实际上需要为您的轮廓创建一个

    其次,您将两个“子网格”一起粉碎成一个三角形数组:

    List<int> trianglesList = new List<int> { };
    List<int> OLtrianglesList = new List<int> { };
    for (int i = 0; i < (n - 2); i++)
    {
        trianglesList.Add(0);
        trianglesList.Add(i + 1);
        trianglesList.Add(i + 2);
    }
    for (int i = 0; i < (n - 2); i++)
    {
        trianglesList.Add(n);
        trianglesList.Add(i + n + 1);
        trianglesList.Add(i + n + 2);
    }
    

    注意OLtrianglesList 没有被使用!

    对两组顶点使用一个列表可能也无济于事:

    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);
        verticesList.Add(new Vector3(x, y, 0f));
    }
    for (int i = 0; i < n; i++)
    {
        x = (radius + OLwidth) * Mathf.Sin((2 * Mathf.PI * i) / n);
        y = (radius + OLwidth) * Mathf.Cos((2 * Mathf.PI * i) / n);
        verticesList.Add(new Vector3(x, y, 0f));
    }
    

    【讨论】:

    • 我可以不让轮廓圆呈现在另一个“后面”吗?无需渲染戒指?我有一个使用相同方法的盒子和坡道对象,它们似乎可以处理相同形状的较大网格在另一个后面就好了
    • 可以,但必须确保轮廓顶点的 Z 值与内部顶点的 Z 值不同。它只会从一侧看起来像一个轮廓。
    • 所以经过更多测试后,我确定问题与 Z-fighting 无关,无论我尝试什么,每个网格都具有相同的材料
    • 啊,我明白了,据我所见,顶点在同一个列表中应该没问题,但是没有使用 OLtrianglesList,谢谢你发现它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多