Unity3D如果要用代码绘制不规则形状的立体图形,必须借助Mesh。其实除了Unity3D提供的Cube、Sphere、Capsule、Cylinder、Plane,可以用GameObject.CreatePrimitive(PrimitiveType.XX);来生成以外,其余的3D图形,如果你不是直接导入模型的话,都要用Mesh去构造。Mesh本质上是一堆由三角形组成的物体。下面用Mesh来画一个矩形平面和圆形面来说明Mesh的使用。
如下图:
一块很简单的白色1x1矩形平面,用Mesh生成的代码如下,可以将如下代码MeshCreate.cs挂载到主摄像机或者空物体则可以直接看到效果了。当然平时这块东西直接用Plane来生成更合适。
using UnityEngine;
using System.Collections;
public class MeshCreate : MonoBehaviour
{
Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.name = "rectangle";
mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) };
mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
return mesh;
}
void Start()
{
GameObject rectangle = new GameObject("rectangle");
rectangle.AddComponent("MeshFilter");
rectangle.GetComponent<MeshFilter>().mesh = CreateMesh();//创建Mesh
//赋予Mesh一个UI/Default材质,颜色为白色,此材质不受灯光影响
MeshRenderer meshRenderer = rectangle.AddComponent<MeshRenderer>();
meshRenderer.material.shader = Shader.Find("UI/Default");
meshRenderer.material.color = Color.white;
}
}
基本上Mesh会赋予到一个空物体GameObject。需要同时赋予MeshFilter与MeshRenderer两部分,一个用来指定Mesh的形状,另一个用来指定这个Mesh所用的材质。这里Mesh使用了纯色材质,没什么好说的。关键是MeshFilter中指定的Mesh。
Mesh由顶点数组vertices、贴图坐标数组uv和三角形数组triangles。这三个概念是Mesh的难点。如下图:
如上文所言,Mesh是由三角形组成的。你用Mesh画出来的平面必须又三角形拼成。这里的矩形平面可以分解为2个三角形拼成,不为什么,显然可以。那么自然而然,矩形的四个顶点的坐标则拼成Mesh顶点数组vertices的内容。而贴图坐标数组uv,是指1x1的材质正方形里面,顶点数组vertices中的顶点所处的位置,以用来截取的这个1x1的正方形,坐标数组uv中只能由坐标取值在[0,1]的二维坐标组成,由于这里只是贴个纯色材质,整个材质正方形上的所有点都是一个意思,所以这里的坐标怎么写都一样,但贴图坐标数组uv中的长度必须和顶点数组vertices的坐标数量相同,Unity3D要求各个顶点都有一个材质落脚点。
至于三角形数组,则是Mesh的形成方式,如下图:
要求Mesh由顶点0->1->2遍历从而形成一个三角形,然后要求由顶点0->2->3由形成一个三角形,从而形成一个最终的Mesh。Unity3D对三角形数组triangles的数组也是三个一读,三个一读。读取方式必须统一方向,统一顺时针或者统一逆时针。所以这里我的三角形数组写了mesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };。
下面举一个更复杂的例子说明Mesh,如下图的圆平面:
对应的CircleCreate.cs如下:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;//用到容器
public class CircleCreate : MonoBehaviour
{
Mesh CreateMesh()
{
Mesh mesh = new Mesh();
mesh.name = "circle";
float circle_radius = 5;//圆的半径
int segment = 360;//分段数
float circle_Z = 0;//圆所处的Z平面
//圆心(0,0)
float circle_center_point_x = 0;
float circle_center_point_y = 0;
List<Vector3> circle_mesh_vertices = new List<Vector3>();
List<Vector2> circle_mesh_uv = new List<Vector2>();
List<int> circle_triangles = new List<int>();
circle_mesh_vertices.Add(new Vector3(circle_center_point_x, circle_center_point_y, circle_Z));
circle_mesh_uv.Add(new Vector2(0, 0));
for (int i = 1; i < segment + 1; i++)
{
float angle_in_circular_segment = (i - 1) * (360 / segment);//圆周角
circle_mesh_vertices.Add(new Vector3(
circle_radius * Mathf.Cos(angle_in_circular_segment) * Mathf.Sin(angle_in_circular_segment),
circle_radius * Mathf.Pow(Mathf.Cos(angle_in_circular_segment), 2),
circle_Z
));
circle_mesh_uv.Add(new Vector2(0, 0));
circle_triangles.Add(0);
circle_triangles.Add(i);
//平时都是0,i,i+1的,但最后一个0,360,1需要特殊处理
if (i + 1 < segment + 1)
{
circle_triangles.Add(i + 1);
}
else
{
circle_triangles.Add(1);
}
}
mesh.vertices = circle_mesh_vertices.ToArray();
mesh.uv = circle_mesh_uv.ToArray();
mesh.triangles = circle_triangles.ToArray();
return mesh;
}
void Start()
{
GameObject circle = new GameObject("circle");
circle.AddComponent("MeshFilter");
circle.GetComponent<MeshFilter>().mesh = CreateMesh();
MeshRenderer meshRenderer = circle.AddComponent<MeshRenderer>();
meshRenderer.material.shader = Shader.Find("UI/Default");
meshRenderer.material.color = Color.white;
}
}
这里的圆弧实质是不平整的,它实质是由360个三角形组成的圆而已。具体绘制思想如下: