Unity-Mesh学习之路
项目介绍
因为之前一直对FogOfWar战争迷雾比较感兴趣,然后当时就在想这个战争迷雾是怎么做出来的,这种问题。后面进入公司,接触的项目是一个沙盒类型的游戏,这个游戏采用的地图就是自动生成的Mesh网格。当时就想去尝试如何进行Mesh的自动生成。在了解的过程中又发现,战旗,三国志这种类型的游戏好像都是采用的自动网格,其中包含六边形网格。这让我慢慢的感兴趣起来了。在逐渐摸索过程中,发现,这个还是很有意思的,哈哈。学习之路,大神多给点意见。也给想学习Mesh 的小伙伴一些些小小的学习经验。请轻喷,哈哈。
项目工程
项目地址:https://gitee.com/SwordsGays/Unity_Mesh.gi 最近较忙然后有重做了系统,一波有bug的传上来还没时间改–!
挂在码云上纯粹是因为github访问太慢–,令人恼火
Unity版本:2017.4.27f1
Mesh介绍
一块Mesh网格,从创建到最终渲染出来在Unity中需要需要经过:
- 创建顶点
- 按照顺时针方向创建三角形(顺时针的原因是:Unity中采用的是左手坐标系,而且只渲染正面)
- 将创建好的Mesh传入MeshFilter(网格过滤器)中
- 再由MeshRanderer将Mesh渲染出来
一个Mesh中包含有顶点数组(Vector3[]),一个三角形索引(int[]),还有uv坐标,法线,这些数据信息。
将他们放入到MeshRanderer中,加载上材质球,将其渲染到场景中去。
工程介绍
此工程是我的个人学习工程,目前位置,只写了两个平面的Mesh,正方形和六边形。按照边长和个数,生成一个Mesh组,可以对每一个Mesh物体进行单独的操作。具体工程可以在项目工程地址上去下载,这里只对工程进行简单介绍.
MeshBase脚本
MeshBase脚本是Mesh网格基类,所有的网格创建派生于此脚本。
所有的平面网格支持两种方向上的创建-xy平面和xz平面
此处使用的Vector向量的归一化没有使用Unity提供的,因为Vector3.normalize是向量的模为1的归一化,而这里需要的是要么为1,要么为0
public enum MeshType
{
Square,
Hex,
}
///放在每一个创建好的Trans上面,用来给外部获取数据提供方法
public class MeshMono : MonoBehaviour
{
public MeshBase _Mesh;
public MeshType _Type;
}
public abstract class MeshBase{
/// <summary>
/// Mesh的顶点组
/// </summary>
protected Vector3[] _vertexs;
/// <summary>
/// 三角形组
/// </summary>
protected int[] _trangles;
protected Vector3 _dir;
public Transform Trans;
public Vector3 Postion;
/// <summary>
/// 边长度
/// </summary>
public float boundLength;
/// <summary>
/// 网格过滤器
/// </summary>
protected MeshFilter _filter;
/// <summary>
/// 渲染器
/// </summary>
protected MeshRenderer _randerer;
/// <summary>
/// Mesh
/// </summary>
protected Mesh _mesh;
#region GetFunction
public Mesh GetMesh {
get {
return _mesh; } }
public Material GetMaterial {
get {
return _randerer == null ? null : _randerer.material; } }
public Material[] GetMaterials {
get {
return _randerer == null ? null : _randerer.materials; } }
#endregion
public MeshBase(float _boundlength,Transform _trans,Vector3 dir)
{
this.Trans = _trans;
this.boundLength = _boundlength;
this.Postion = _trans.position;
_filter = _trans.gameObject.GetComponent<MeshFilter>();
if(_filter == null) _filter = _trans.gameObject.AddComponent<MeshFilter>();
_randerer = _trans.gameObject.GetComponent<MeshRenderer>();
if (_randerer == null) _randerer = _trans.gameObject.AddComponent<MeshRenderer>();
_mesh = new Mesh();
VectorNomalized(dir);
}
//将方向归一化
private void VectorNomalized(Vector3 dir)
{
_dir.x = dir.x != 0 ? 1 : 0;
_dir.y = dir.y != 0 ? 1 : 0;
_dir.z = dir.z != 0 ? 1 : 0;
}
public virtual void SetColor(Color _color)
{
_randerer.material.color = _color;
}
public virtual void SetColor32(Color32 _color)
{
_randerer.material.color = _color;
}
/// <summary>
/// 设置材质球
/// </summary>
/// <param name="_mat">已经加载好的材质球</param>
public virtual void SetMaterial(Material _mat)
{
_randerer.material = _mat;
}
/// <summary>
/// 设置材质球
/// </summary>
/// <param name="path">材质球所在地址(使用Resources加载)</param>
public virtual void SetMaterial(string path)
{
Material _mat = Resources.Load<Material>(path);
SetMaterial(_mat);
}
/// <summary>
/// 生成Mesh
/// </summary>
public abstract void CreateMesh();
/// <summary>
/// 范围检测
/// </summary>
/// <param name="point">坐标点</param>
/// <returns></returns>
public abstract bool IsInBoundsArea<