Unity---------Mesh理解

Mesh顾名思义“网格”,Unity3D里面所有的模型都是由Mesh组成的,UI也不例外。

例如下图,模型上的一个个小网格就是Mesh,这些Mesh有不同的三维顶点(Vector3),共同组成了一个3D模型。

Unity3D中Mesh的基本单位是三角形,学习应该由浅入深,所以今天我们就从最基本最简单的等腰三角形开始画起。

本文作者尚为初学者,如有理解不到位的地方,欢迎指正。

 

首先我们新建一个名为TestTriangle的CSharp脚本,然后打开TestTriangle,我们开始编写代码。

[csharp] view plain copy

  1. using UnityEngine;
  2. using System.Collections;
  3. /* ==============================================================================
  4. * 功能描述:创建三角形Mesh
  5. * 创 建 者:Eci
  6. * 创建日期:2016/09/04
  7. * ==============================================================================*/
  8. [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
  9. public class TestTriangle : MonoBehaviour {
  10. public float sideLength = 2;
  11. public float angleDegree = 100;
  12. private MeshFilter meshFilter;
  13. [ExecuteInEditMode]
  14. private void Awake()
  15. {
  16. meshFilter = GetComponent<MeshFilter>();
  17. meshFilter.mesh = Create (sideLength, angleDegree);
  18. }
  19. private void Update()
  20. {
  21. }
  22. private Mesh Create(float sideLength, float angleDegree)
  23. {
  24. Mesh mesh = new Mesh();
  25. Vector3[] vertices = new Vector3[3];
  26. float angle = Mathf.Deg2Rad * angleDegree;
  27. float halfAngle = angle / 2;
  28. vertices [0] = Vector3.zero;
  29. float cosA = Mathf.Cos (halfAngle);
  30. float sinA = Mathf.Sin (halfAngle);
  31. vertices [1] = new Vector3 (cosA * sideLength, 0, sinA * sideLength);
  32. vertices [2] = new Vector3 (cosA * sideLength, 0, -sinA * sideLength);
  33. int[] triangles = new int[3];
  34. triangles [0] = 0;
  35. triangles [1] = 1;
  36. triangles [2] = 2;
  37. mesh.vertices = vertices;
  38. mesh.triangles = triangles;
  39. Vector2[] uvs = new Vector2[vertices.Length];
  40. for (int i = 0; i < uvs.Length; i++)
  41. {
  42. uvs[i] = Vector2.zero;
  43. }
  44. mesh.uv = uvs;
  45. return mesh;
  46. }
  47. }

RequireComponent这一行,表示我们需要MeshRenderer和MeshFilter这两个组件,当我们将TestTriangle的代码挂在GameObject上的时候,会自动添加这两个组件。而我们要移除MeshRenderer或MeshFilter的时候,编辑器就会提示不能移除。

然后我们给出了两个公开变量,sideLength边长和angleDegree角度,因为我们这里要画的是等腰三角形,这代表的是等腰边长和等腰边长的夹角。

ExecuteInEditMode表示会在编辑器模式下运行。

Awake里,我们获取了MeshFilter并为它创建了Mesh。

Create方法里面,我们看到,先后为新建的Mesh创建了vertices(定点),triangles(三角形),uv(纹理坐标)。

vertices很简单,就是计算三角形三个顶点的坐标,因为是个二维图形,所以y坐标都为零。

triangles里保存的是vertices的下标。

uv暂时我们用不到,所以全部设为零。在后面文章中我们会介绍uv的用法。

最后返回mesh。

在编辑器里,点击运行,我们就可以看到一个紫色(因为没有材质)的三角形。

但是只能在运行的时候才看得到这个三角形,编辑器里看不到怎么办?添加下面这段代码:

[csharp] view plain copy

  1. void OnDrawGizmos()
  2. {
  3. Gizmos.color = Color.gray;
  4. DrawMesh();
  5. }
  6. void OnDrawGizmosSelected()
  7. {
  8. Gizmos.color = Color.green;
  9. DrawMesh();
  10. }
  11. private void DrawMesh()
  12. {
  13. Mesh mesh = Create(sideLength, angleDegree);
  14. int[] tris = mesh.triangles;
  15. Gizmos.DrawLine(mesh.vertices[tris[0]], mesh.vertices[tris[1]]);
  16. Gizmos.DrawLine(mesh.vertices[tris[0]], mesh.vertices[tris[2]]);
  17. Gizmos.DrawLine(mesh.vertices[tris[1]], mesh.vertices[tris[2]]);
  18. }

关于OnDrawGizmos和OnDrawGizmosSelected可以参考下面这个链接:
http://www.ceeger.com/Script/Gizmos/Gizmos.html

简单来讲就是在编辑器模式下,绘制辅助线框。

这样一个简单的等腰三角形Mesh的绘制就完成了。什么?你不满意?我们稍微整理一下代码:

[csharp] view plain copy

  1. using UnityEngine;
  2. using System.Collections;
  3. /* ==============================================================================
  4. * 功能描述:创建三角形Mesh
  5. * 创 建 者:Eci
  6. * 创建日期:2016/09/04
  7. * ==============================================================================*/
  8. [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
  9. public class TestTriangle : MonoBehaviour {
  10. public float sideLength = 2;
  11. public float angleDegree = 100;
  12. private static readonly int ANGLE_DEGREE_PRECISION = 1000;
  13. private static readonly int SIDE_LENGTH_PRECISION = 1000;
  14. private MeshFilter meshFilter;
  15. private TriangleMeshCreator creator = new TriangleMeshCreator();
  16. [ExecuteInEditMode]
  17. private void Awake()
  18. {
  19. meshFilter = GetComponent<MeshFilter>();
  20. }
  21. private void Update()
  22. {
  23. meshFilter.mesh = creator.CreateMesh(sideLength, angleDegree);
  24. }
  25. void OnDrawGizmos()
  26. {
  27. Gizmos.color = Color.gray;
  28. DrawMesh();
  29. }
  30. void OnDrawGizmosSelected()
  31. {
  32. Gizmos.color = Color.green;
  33. DrawMesh();
  34. }
  35. private void DrawMesh()
  36. {
  37. Mesh mesh = creator.CreateMesh(sideLength, angleDegree);
  38. int[] tris = mesh.triangles;
  39. Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[0]]), transformToWorld(mesh.vertices[tris[1]]));
  40. Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[0]]), transformToWorld(mesh.vertices[tris[2]]));
  41. Gizmos.DrawLine(transformToWorld(mesh.vertices[tris[1]]), transformToWorld(mesh.vertices[tris[2]]));
  42. }
  43. private Vector3 transformToWorld(Vector3 src)
  44. {
  45. return transform.TransformPoint(src);
  46. }
  47. private class TriangleMeshCreator
  48. {
  49. private float _sideLength;
  50. private float _angleDegree;
  51. private Mesh _cacheMesh ;
  52. public Mesh CreateMesh(float sideLength, float angleDegree)
  53. {
  54. if (checkDiff(sideLength, angleDegree))
  55. {
  56. Mesh newMesh = Create(sideLength, angleDegree);
  57. if (newMesh != null)
  58. {
  59. _cacheMesh = newMesh;
  60. this._sideLength = sideLength;
  61. this._angleDegree = angleDegree;
  62. }
  63. }
  64. return _cacheMesh;
  65. }
  66. private Mesh Create(float sideLength, float angleDegree)
  67. {
  68. Mesh mesh = new Mesh();
  69. Vector3[] vertices = new Vector3[3];
  70. float angle = Mathf.Deg2Rad * angleDegree;
  71. float halfAngle = angle / 2;
  72. vertices [0] = Vector3.zero;
  73. float cosA = Mathf.Cos (halfAngle);
  74. float sinA = Mathf.Sin (halfAngle);
  75. vertices [1] = new Vector3 (cosA * sideLength, 0, sinA * sideLength);
  76. vertices [2] = new Vector3 (cosA * sideLength, 0, -sinA * sideLength);
  77. int[] triangles = new int[3];
  78. triangles [0] = 0;
  79. triangles [1] = 1;
  80. triangles [2] = 2;
  81. mesh.vertices = vertices;
  82. mesh.triangles = triangles;
  83. Vector2[] uvs = new Vector2[vertices.Length];
  84. for (int i = 0; i < uvs.Length; i++)
  85. {
  86. uvs[i] = Vector2.zero;
  87. }
  88. mesh.uv = uvs;
  89. return mesh;
  90. }
  91. private bool checkDiff(float sideLength, float angleDegree)
  92. {
  93. return (int)((sideLength - this._sideLength) * SIDE_LENGTH_PRECISION) != 0 ||
  94. (int)((angleDegree - this._angleDegree) * ANGLE_DEGREE_PRECISION) != 0;
  95. }
  96. }
  97. }

为GameObject的MeshRenderer添加材质,我们就可以看到有颜色的三角形了。因为uv值都为0,所以是单一颜色。不过没关系,下一堂课,我们会为三角形添加不同的纹理。

附上代码下载链接

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-17 11:26:01

Unity---------Mesh理解的相关文章

Unity Mesh 初体验

什么是Mesh Mesh是Unity中的一个组件,称为网格组件.通俗的讲,Mesh是指模型的网格,3D模型是由多边形拼接而成,而一个复杂的多边形,实际上是由多个三角面拼接而成.所以一个3D模型的表面是由多个彼此相连的三角面构成.三维空间中,构成这些三角面的点以及三角形的边的集合就是Mesh.如下图所示: mesh.png 所以建模型就是就是要画一些列的三角形,而定位一个三角形就是只需要3个顶点而已.很简单哦. 比如我们要画一个五边形,如下: demo1.png 它有五个顶点,但是在Unity中是

Unity 全面理解加载和内存管理

最近一直在和这些内容纠缠,把心得和大家共享一下: Unity里有两种动态加载机制:一是Resources.Load,一是通过AssetBundle,其实两者本质上我理解没有什么区别.Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时动态加载,可以指定路径和来源的. 其实场景里所有静态的对象也有这么一个加载过程,只是Unity后台替你自动完成了. 详细说一下细节概念:AssetBundle运行时加载:来自

Unity内存理解(转)

Unity3D 里有两种动态加载机制:一个是Resources.Load,另外一个通过AssetBundle,其实两者区别不大. Resources.Load就是从一个缺省打进程序包里的AssetBundle里加载资源,而一般AssetBundle文件需要你自己创建,运行时 动态加载,可以指定路径和来源的. 其实场景里所有静态的对象也有这么一个加载过程,只是Unity3D后台替你自动完成了. 详细说一下细节概念:AssetBundle运行时加载:来自文件就用CreateFromFile(注意这种

【小松教你手游开发】【unity实用技能】Unity Mesh更新的时候增加内存

Unity在Mesh更新的时候会增加内存,一般的方法是使用数组去填入. Vector3[] vertices = new Vector3[segmentCount * 4]; Vector3[] normals = new Vector3[segmentCount * 4]; Vector4[] tangents = new Vector4[segmentCount * 4]; Color[] colors = new Color[segmentCount * 4]; Vector2[] uvs

【Unity】理解协程的原理1——实现一个自己的WaitForSeconds

协程的所能达到的效果就是在指定的时间点上执行需要执行的代码,Unity中开始一个协程的函数是StartCoroutine,而提供的延迟的类有以下几种分别是 new WaitForEndOfFrame; //等待一帧 new WaitForFixedUpdate; //等待一个FixedUpdate(固定时间间隔) new WaitForSeconds; //等待X秒 new WWW; //等待外部资源加载完毕 本文就针对其中的WaitForSeconds实现进行探究. 因为在开发过程中,很多时候

unity Mesh(网格)的使用

创建两个三角形合成的矩形网格: GameObject obj= new GameObject(); MeshRenderer meshRenderer=obj.AddComponent<MeshRenderer>(); MeshFilter meshFilter=obj.AddComponent<MeshFilter>(); //渲染材质 meshRenderer.material=new Material(Shader.Find("Sprites/Default&quo

unity mesh baker(游戏场景优化插件)

模型+灯光测试结果: 执行之前使用的Draw Calls和内存 执行之后使用的Draw Calls和内存 ?模型合并规则: 1.非同样的静态模型才需要合并 同样模型(复制的)不用合并 2.UV无重复的模型可用Mesh Baker合并 重复的Mesh Baker会出错 有需要可以在制作软件里合并 3.使用同样材质模型可以合并 使用不同材质的模型不能合并 4.合并模型贴图大小必须为2的N次幂 需选择合适大小以免浪费空间或效果不理想 不要通过贴图设置另外更改大小 灯光烘焙优化场景效果和资源方法: 1.

解读Unity中的CG编写Shader系列五——理论知识

经过前面的系列文章中的三个例子,尽管代码简单,但是我想应该还有些地方没有100%弄明白,我们现在得回过头来补充一些必备的数学.图形学知识 1.图形管道 第一个例子中我有提到顶点着色和片段着色在整个图形绘制过程中属于一个环节,整个过程叫做管道,这个管道的所有环节包括: 在整个管道中,只有顶点着色与片段着色是可编程的,顶点数据和帧缓存是具体的数据,剩下的环节是固定功能的环节,即不能用cg去编程的环节. 2.数据流 3.语义.特殊参数(uniform) 前文已经大量接触到语义,语义的存在意义可以理解为

什么是网格?

Unity Mesh 首先了解一下Unity官方对Mesh的解释:网格包含顶点和多个三角面数组,三角面数组只是顶点数组的下标,一个三角面对应三个下标.对于每一个顶点对会有法线,UV纹理坐标,颜色和切线.这些可以根据意愿增减.所有顶点信息都会保存在单独的同样大小的数组中,所以如果你的网格有10个顶点,那么你需要大小为10的数组来保存法线和其他属性. 介绍: Mesh是Unity中的一个组件,称为网格组件,一般来说,Mesh指模型的网格,3D模型是由多边形拼接而成的,而一个复杂的多边形实际上是由多个

ACTGame项目

项目地址:https://github.com/alonecat06/ACTGame游戏地址:http://pan.baidu.com/s/1hqD3IYw 项目是一个自制单机动作游戏demo,方向是手游,使用Unity5,5月中开工至今. 做这个项目,是为加深自己对Unity的理解和展示自己的技术而自行制作的一个项目.目标是一个可换装.选关卡进行战斗的单机手游. 2015.06.30================================ 游戏已发布为pc版和android版,可以在游