Unity 制作一个简单的Mesh网格
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 制作一个简单的Mesh网格相关的知识,希望对你有一定的参考价值。
参考技术A 为了渲染出我们自制的Mesh,我们首先在一个空组件上增加MeshFilter和MeshRenderer。MeshFilter是针对我们这个GameObject存储的Mesh,Mesh Renderer组件就是读取自身的MeshFilter来获得mesh进行渲染,所以这两个组件是配套使用的。
网格就如字面意思一样就是由点和线组成的东西。
图2是一个平面网格,图3就是我们常见的cube网格。
而我们常见的网格的最小单元是一个三角形,也就是3个顶点组成的最小单元。
制作一个Mesh非常的简单,我们只需要new一个Mesh然后赋值给我们的MeshFilter组件就可以拉。
但是这样我们还是看不出个什么来因为网格没有其他的一些信息,也没有顶点信息。
到这一步我们就要开始正式的为我们制作的Mesh增加顶点啦,首先尝试加3个点。
这样我们的顶点坐标就成功的加到了我们Mesh里拉。
这里的坐标点对应的是世界坐标的坐标点。
这里的0是顶点坐标信息下标里的0,是和vertices对应上的。存储的就是顶点坐标的下标。
但是设置到这你就发现没用啊,场景里没有生成东西啊什么反应都没有。
因为我们需要连接的是一个最小单元也就是一个三角形,所以从连接上来看我们是一条线,不能形成一个面啦,所以我们只需要稍作调整就可以得到一个三角面啦。
这时候点击Mesh查看就能看到一个三角面的网格啦;
场景中也对应的出现了一个紫色的没有材质的三角面。
但是有的朋友可能生成之后看不到场景里的三角面,如下图。
这是为什么会这样呢?首先需要确认你的MeshRenderer组件的materials size大于0
排除这个问题就到了一个需要注意的点triangles,Mesh的三角下标信息。
仔细对比图6 和 图7的坐标系发现 图6显示出来的三角面试是在z轴的正方向,而不显示的图7是在z轴的反方向。
这是因为我们只渲染了一个面,所以背面信息没有渲染。
那是什么信息决定了正面渲染的呢?
其实就是我们的三角面下标顺序。
我们这里的顺序是 0 2 1是一个顺时针旋转。所以是z轴正面渲染。
当我们使用 0 1 2点顺序 也就是 逆时针顺序渲染 看到的 三角面应该是在z轴反面渲染
当我们给MeshRenderer里添加材质你会发现变黑了,为什么是变黑呢?是因为材质没有对应上这个Mesh,这个Mesh的没有uv坐标信息。那么uv坐标到底是什么?
uv坐标就是横坐标为u,纵坐标为v的一个坐标系,一般取值范围是在(0,1)之间。它代表贴图信息的位置关系,贴图每个像素点对应上的具体位置。
如果你加载出来的贴图是一个纯黑的图,就要考虑是不是Auto Greerate lighting 没有设置为on。
在了解什么是法线的前提下,我们先来看看法线对Mesh有什么影响。
效果是不是显而易见的,当没有法线的时候图片没有光照信息,不反射光照看起来灰蒙蒙的。
而图13 14是加了法线的,它就会受到光线信息的影响,从不同的角度去看都有不一样的效果。
法线分为顶点法线和面法线。在这个三角面上有三个顶点 和一个三角面,对应的也就有3个顶点法线和一个面法线,法线垂直于点、面,方向朝外是一个向量。
在这里简单的添加法线信息可以使用unity带的
当然你也可以自己为它添加法线信息。
这里为什么是-1,不是正1。 我们刚刚说过了法线的方向朝外,当我们灯光照射方向和法线方向相同就看不出光照信息的效果,而相反的话就能很好的反应出受光照的反射效果。
这里只是简单的介绍Mesh网格的一些基础的信息,肯定有很多地方有歧义 也是不好意思啦,如果有不正确的地方欢迎指出。谢谢大家。
unity---Mesh网格编程
目录
unity---Mesh网格编程(二)说了用mesh 创建一个3X3的面
1.创建一个正方体
using UnityEngine;
//挂载到物体时自动添加 MeshFilter 与 MeshRenderer 组件
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Mesh3 : MonoBehaviour
private Vector3[] _vertices;
private int[] _triangles;
void Start()
Mesh mesh = new Mesh();
MeshFilter filter = GetComponent<MeshFilter>();
filter.mesh = mesh;
mesh.name = "Mesh3";
GenerateVextex();
GenerateTriangle();
mesh.vertices = _vertices;
mesh.triangles = _triangles;
//正方体顶点数8个
private void GenerateVextex()
_vertices = new Vector3[8];
//上面
_vertices[0] = new Vector3(-0.5f, -0.5f, -0.5f);
_vertices[1] = new Vector3(0.5f, -0.5f, -0.5f);
_vertices[2] = new Vector3(-0.5f, -0.5f, 0.5f);
_vertices[3] = new Vector3(0.5f, -0.5f, 0.5f);
//下面
_vertices[4] = new Vector3(-0.5f, 0.5f, -0.5f);
_vertices[5] = new Vector3(0.5f, 0.5f, -0.5f);
_vertices[6] = new Vector3(-0.5f, 0.5f, 0.5f);
_vertices[7] = new Vector3(0.5f, 0.5f, 0.5f);
//正方体6个面的顶点下标,注意法线朝向
private void GenerateTriangle()
_triangles = new int[36];
//底面三角1
_triangles[0] = 0;
_triangles[1] = 1;
_triangles[2] = 2;
//底面三角2
_triangles[3] = 1;
_triangles[4] = 3;
_triangles[5] = 2;
//前面三角1
_triangles[6] = 0;
_triangles[7] = 4;
_triangles[8] = 5;
//前面三角2
_triangles[9] = 5;
_triangles[10] = 1;
_triangles[11] = 0;
//后面三角1
_triangles[12] = 3;
_triangles[13] = 7;
_triangles[14] = 6;
//后面三角2
_triangles[15] = 6;
_triangles[16] = 3;
_triangles[17] = 2;
//左面三角1
_triangles[18] = 6;
_triangles[19] = 4;
_triangles[20] = 0;
//左面三角2
_triangles[21] = 4;
_triangles[22] = 0;
_triangles[23] = 2;
//右面三角1
_triangles[24] = 1;
_triangles[25] = 5;
_triangles[26] = 7;
//右面三角2
_triangles[27] = 7;
_triangles[28] = 3;
_triangles[29] = 1;
//上面三角1
_triangles[30] = 6;
_triangles[31] = 7;
_triangles[32] = 4;
//上面三角2
_triangles[33] = 7;
_triangles[34] = 5;
_triangles[35] = 4;
2.创建一个立方体
using System.Collections;
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Mesh3 : MonoBehaviour
public int xGridCount, yGridCount, zGridCount;
private Vector3[] _vertices;
private int[] _triangles;
private int _t = 0, _v = 0;
void Start()
Mesh mesh = new Mesh();
MeshFilter filter = GetComponent<MeshFilter>();
filter.mesh = mesh;
mesh.name = "Mesh3";
StartCoroutine(GenerateMesh(mesh));
private IEnumerator GenerateMesh(Mesh mesh)
yield return StartCoroutine(GenerateVextex());
mesh.vertices = _vertices;
yield return StartCoroutine(GenerateTriange(mesh));
//计算顶点数
private int GetVextexCount()
//公共-顶点数
int connerVertexCount = 8;
//边--顶点数
int edgeVertexCount = (xGridCount + yGridCount + zGridCount - 3) * 4;
//内部顶点数
int faceVertexCount = (xGridCount - 1) * (yGridCount - 1) * 2
+ (zGridCount - 1) * (yGridCount - 1) * 2
+ (xGridCount - 1) * (zGridCount - 1) * 2;
return connerVertexCount + edgeVertexCount + faceVertexCount;
//生成顶点
private IEnumerator GenerateVextex()
_vertices = new Vector3[GetVextexCount()];
int index = 0;
//循环生成左右前后4个面的顶点
for (int y = 0; y < yGridCount + 1; y++)
//底部正方形-第一条边的顶点
for (int x = 0; x < xGridCount + 1; x++, index++)
_vertices[index] = new Vector3(x, y, 0);
yield return null;
//底部正方形-第二条边的顶点
for (int z = 1; z < zGridCount + 1; z++, index++)
_vertices[index] = new Vector3(xGridCount, y, z);
yield return null;
//底部正方形-第三条边的顶点
for (int x = xGridCount - 1; x >= 0; x--, index++)
_vertices[index] = new Vector3(x, y, zGridCount);
yield return null;
//底部正方形-第四条边的顶点
for (int z = zGridCount - 1; z > 0; z--, index++)
_vertices[index] = new Vector3(0, y, z);
yield return null;
//生成上面的顶点
for (int z = 1; z < zGridCount; z++)
for (int x = 1; x < xGridCount; x++, index++)
_vertices[index] = new Vector3(x, yGridCount, z);
yield return null;
//生成下面的顶点
for (int z = 1; z < zGridCount; z++)
for (int x = 1; x < xGridCount; x++, index++)
_vertices[index] = new Vector3(x, 0, z);
yield return null;
//计算顶点序列下标数
private int GetTriangeCount()
return xGridCount * yGridCount * 4 + xGridCount * zGridCount * 4 + yGridCount * zGridCount * 4;
//顶点绘制三角面序列
private IEnumerator GenerateTriange(Mesh mesh)
_triangles = new int[GetTriangeCount() * 3];
int circleVextexCount = 2 * xGridCount + 2 * zGridCount;
yield return StartCoroutine(GenerateSide(mesh, circleVextexCount));
yield return StartCoroutine(GenerateTop(mesh, circleVextexCount));
yield return StartCoroutine(GenerateBottom(mesh, circleVextexCount));
private IEnumerator GenerateSide(Mesh mesh, int circleVextexCount)
for (int y = 0; y < yGridCount; y++)
for (int i = 0; i < circleVextexCount; i++, _v++, _t += 6)
SetQuad(_triangles, _t, _v, _v + 1, _v + circleVextexCount, _v + 1 + circleVextexCount, circleVextexCount);
mesh.triangles = _triangles;
yield return null;
private IEnumerator GenerateTop(Mesh mesh, int circleVextexCount)
//第一行前三个面
for (int x = 0; x < xGridCount - 1; x++, _v++, _t += 6)
SetQuad(_triangles, _t, _v, _v + 1, _v + circleVextexCount - 1, _v + circleVextexCount);
mesh.triangles = _triangles;
yield return null;
//第一行第四个面
SetQuad(_triangles, _t, _v, _v + 1, _v + circleVextexCount - 1, _v + 2);
mesh.triangles = _triangles;
_t += 6;
yield return null;
int vMin = circleVextexCount * (yGridCount + 1) - 1;
int vMid = vMin + 1;
int vMax = _v + 2;
//中间行所有面
for (int z = 0; z < zGridCount - 2; z++, vMin--, vMid++, vMax++)
//第一个面
SetQuad(_triangles, _t, vMin, vMid, vMin - 1, vMid + xGridCount);
mesh.triangles = _triangles;
_t += 6;
yield return null;
//中间面片
for (int i = 0; i < xGridCount - 2; i++, _t += 6, vMid++)
SetQuad(_triangles, _t, vMid, vMid + 1, vMid + xGridCount - 1, vMid + xGridCount);
mesh.triangles = _triangles;
yield return null;
//最后一个面
SetQuad(_triangles, _t, vMid, vMax, vMid + xGridCount - 1, vMax + 1);
mesh.triangles = _triangles;
_t += 6;
yield return null;
int vTop = vMin - 2;
//第一个面
SetQuad(_triangles, _t, vMin, vMid, vMin - 1, vTop);
mesh.triangles = _triangles;
_t += 6;
yield return null;
for (int i = 0; i < xGridCount - 2; i++, vMid++, vTop--)
//中间面
SetQuad(_triangles, _t, vMid, vMid + 1, vTop, vTop - 1);
mesh.triangles = _triangles;
_t += 6;
yield return null;
//最后一行最后一个面
SetQuad(_triangles, _t, vMid, vTop - 2, vTop, vTop - 1);
mesh.triangles = _triangles;
_t += 6;
yield return null;
private IEnumerator GenerateBottom(Mesh mesh, int circleVextexCount)
int vMin = circleVextexCount - 1;
int vMid = _vertices.Length - (xGridCount - 1) * (zGridCount - 1);
//第一行,第一面
SetQuad(_triangles, _t, vMin, vMid, 0, 1);
_t += 6;
mesh.triangles = _triangles;
yield return null;
int vMax = 1;
//第一行,中间面
for (int i = 0; i < xGridCount - 2; i++, _t += 6, vMax++, vMid++)
SetQuad(_triangles, _t, vMid, vMid + 1, vMax, vMax + 1);
mesh.triangles = _triangles;
yield return null;
//第一行,最后面
SetQuad(_triangles, _t, vMid, vMax + 2, vMax, vMax + 1);
_t += 6;
mesh.triangles = _triangles;
yield return null;
vMid++;
vMax += 2;
for (int z = 0; z < zGridCount - 2; z++, vMin--, vMid++, vMax++)
//第一面
SetQuad(_triangles, _t, vMin - 1, vMid, vMin, vMid - xGridCount + 1);
_t += 6;
mesh.triangles = _triangles;
yield return null;
//中间面
for (int i = 0; i < xGridCount - 2; i++, _t += 6, vMid++)
SetQuad(_triangles, _t, vMid, vMid + 1, vMid - xGridCount + 1, vMid - xGridCount + 2);
mesh.triangles = _triangles;
yield return null;
//最后面
SetQuad(_triangles, _t, vMid, vMax + 1, vMid - xGridCount + 1, vMax);
_t += 6;
mesh.triangles = _triangles;
yield return null;
vMid = vMid - xGridCount + 1;
//最后行,第一面
SetQuad(_triangles, _t, vMin - 1, vMin - 2, vMin, vMid);
_t += 6;
mesh.triangles = _triangles;
yield return null;
int vBottom = vMin - 2;
//最后行,中间面
for (int i = 0; i < xGridCount - 2; i++, _t += 6, vBottom--, vMid++)
SetQuad(_triangles, _t, vBottom, vBottom - 1, vMid, vMid + 1);
mesh.triangles = _triangles;
yield return null;
//最后行,最后面
SetQuad(_triangles, _t, vBottom, vBottom - 1, vMid, vBottom - 2);
_t += 6;
mesh.triangles = _triangles;
yield return null;
private void SetQuad(int[] triangles, int i, int v00, int v10, int v01, int v11, int circleVextexCount)
v10 = (v00 / circleVextexCount) * circleVextexCount + v10 % circleVextexCount;
v11 = (v01 / circleVextexCount) * circleVextexCount + v11 % circleVextexCount;
SetQuad(triangles, i, v00, v10, v01, v11);
//每个面片 6个顶点下标序列
private void SetQuad(int[] triangles, int i, int v00, int v10, int v01, int v11)
//第1个三角面
triangles[i] = v00;
triangles[i + 1] = v01;
triangles[i + 2] = v10;
//第2个三角面
triangles[i + 3] = v01;
triangles[i + 4] = v11;
triangles[i + 5] = v10;
以上是关于Unity 制作一个简单的Mesh网格的主要内容,如果未能解决你的问题,请参考以下文章