首先所有渲染的物体都是由mesh网格组成。mesh的基本单位图元为点,线,三角形。可以说所有的游戏物体都是绘制点,线,三角形的集合。
mesh是unity的一个类它下边有vertices(顶点),UV(纹理坐标),Normal(法向量),triangles(三角序列)。
uv:任何一个图形上面它的x轴即为u,y轴为v,可以通过它把图形绘制到3d物体(mesh)上。
实现简单的图形绘制(必须有Mesh Filter和MeshRender组件)
(1)创建一个空物体
(2)编写代码
有时候会遇见赋完材质时物体为黑色,这时候给脚本添加法向量即可,原因是法向量可能是朝下的这时候渲染出来的物体为光的背面。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//通过这句代码为游戏物体强制添加组件
[RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
public class MeshStudy : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Mesh mesh = new Mesh();
MeshFilter meshFilter = GetComponent<MeshFilter>();
meshFilter.mesh = mesh;
mesh.Clear();
mesh.name = "mesh_01";
mesh.vertices = GetVertexs();
mesh.triangles = GetTranigles();
mesh.uv = Getuv();
}
private Vector2[]Getuv()
{
return new Vector2[]
{
new Vector2(0,0),
new Vector2(1,0),
new Vector2(1,1),
new Vector2(0,1)
};
}
private Vector3 [] GetVertexs()
{
return new Vector3[]
{
new Vector3(0,0,0),
new Vector3(1, 0, 0),
new Vector3(1,1,0),
new Vector3(0,1,0)
};
}
private int [] GetTranigles()
{
return new int[] { 0, 2, 1, 0, 3, 2 };
}
// Update is called once per frame
void Update()
{
}
}
实现效果如图所示(第一个为不加材质)
实平面的绘制
(1)先让脚本给物体添加那两个组件(meshRender,meshFilter)
(2)给mesh的顶点初始化并赋值
(3)给mesh的三角形序列赋值
(4)uv赋值,法向量赋值
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class Challenge : MonoBehaviour
{
public int X = 3, Y = 2;
private Vector3[] vertices;
private Vector2[] uv;
private Vector3[] normals;
// Start is called before the first frame update
void Start()
{
Mesh mesh = new Mesh();
MeshFilter filter = GetComponent<MeshFilter>();
filter.mesh = mesh;
mesh.name = "_mesh01";
vertices = new Vector3[(X + 1) * (Y + 1)];
uv = new Vector2[vertices.Length];
normals =new Vector3[vertices.Length];
StartCoroutine(GeneratePlane(mesh));
}
// Update is called once per frame
void Update()
{
}
private IEnumerator GeneratePlane(Mesh mesh)
{
yield return GetVertices();
mesh.vertices = vertices;
mesh.uv = uv;
mesh.normals = normals;
yield return GetTriangles(mesh);
}
private Vector3 GetNormal(int y)
{
if(y%2==0)
{
return Vector3.up;
}
else
{
return Vector3.down;
}
// return Vector3.up;
}
private IEnumerator GetVertices()
{
for(int y= 0,i=0;y<Y+1;y++)
{
for(int x= 0;x<X+1;x++,i++)
{
vertices[i] = new Vector3(x, y);
normals[i] = GetNormal(y);
uv[i] = new Vector2((float)x / X, (float)y / Y);
yield return new WaitForSeconds(0.2f);
}
}
}
private IEnumerator GetTriangles(Mesh mesh)
{
int[] triangles = new int[(X * Y) * 6];
for(int startIndex =0,y=0,trianglesIndex=0;y<Y&&startIndex<vertices.Length&&trianglesIndex<triangles.Length;y++,startIndex++)
{
for(int x=0;x<X;x++,startIndex++,trianglesIndex+=6)
{
triangles[trianglesIndex] = startIndex;
triangles[trianglesIndex + 1] = startIndex + 1 + X;
triangles[trianglesIndex + 2] = startIndex + 1;
mesh.triangles = triangles;
yield return new WaitForSeconds(0.2f);
triangles[trianglesIndex + 3] = startIndex + X + 1;
triangles[trianglesIndex + 4] = startIndex + X + 2;
triangles[trianglesIndex + 5] = startIndex + 1;
mesh.triangles = triangles;
yield return new WaitForSeconds(0.2f);
}
}
}
private void OnDrawGizmos()
{
for(int i=0;i<vertices.Length;i++)
{
Gizmos.DrawSphere(vertices[i],0.1f);
}
}
}
实现效果如图所示