上一篇是初次接触程序化网格,所以很多原理不懂,出现的许多问题也是自己不熟悉导致,现在研究了一段时间,之前很多问题已经不存在了,今天把完整的优化后的创建任意长度的矩形的功能记录一下。
实现的功能:
1.连续创建任意长度矩形
2.接缝处可以无缝衔接
实现效果:
实现代码:
using UnityEngine;
public class CreateStrechMesh3 : MonoBehaviour
{
private void Update()
{
CreateCustomWallMod();
}
[SerializeField]
private Material wallMat = null; //墙体材质
[SerializeField]
private LayerMask planeLayer = 0; //地面层
[SerializeField]
private float width = 1; //墙体宽度
[SerializeField]
private float height = 3.4f; //墙体高度
private float length = 0; //墙体长度
private RaycastHit hit; //
private int clickCount = 0; //点击次数,第一次点击创建,以后每一次点击先结束创建,在创建新墙体
private GameObject curWall = null; //创建的墙体
private Mesh mesh = null; //墙体mesh
private MeshRenderer meshRender = null; //墙体meshrender
private MeshFilter meshFilter = null; //墙体meshfilter
private bool isStartCreate = false; //开始创建
private Vector3[] vertics = new Vector3[24]; //墙体顶点
private int[] triangles = new int[36]; //墙体三角面
private Vector2[] UVs = new Vector2[24]; //墙体uv
private Vector3 originPos = Vector3.zero; //墙体起始点
private GameObject preWall = null; //上一个墙体缓存
private Mesh preMesh = null; //上一个墙体mesh
private Vector3[] preVertics = new Vector3[24]; //上一个墙体顶点
private float preLength = 0; //上一个墙体长度
private void CreateCustomWallMod()
{
if (Input.GetMouseButtonDown(1))
{
if (curWall != null)
{
Destroy(curWall);
curWall = null;
}
preWall = null;
clickCount = 0;
isStartCreate = false;
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 100, planeLayer))
{
if (Input.GetMouseButtonDown(0))
{
isStartCreate = true;
clickCount++;
if (clickCount == 1)
{
StartCreateCustomWall(hit.point);
}
else
{
EndCreateCustomWall(hit.point);
StartCreateCustomWall(hit.point);
}
}
if (isStartCreate)
{
RefreshMeshMod(hit.point);
}
}
}
/// <summary>
/// 开始创建自定义墙体
/// </summary>
/// <param name="_pos"></param>
private void StartCreateCustomWall(Vector3 _pos)
{
curWall = new GameObject();
meshRender = curWall.AddComponent<MeshRenderer>();
if (wallMat != null)
{
meshRender.sharedMaterial = wallMat;
}
else
{
meshRender.sharedMaterial = new Material(Shader.Find("Standard"));
}
meshFilter = curWall.AddComponent<MeshFilter>();
mesh = meshFilter.mesh;
curWall.transform.position = _pos;
originPos = _pos;
length = 0;
vertics = new Vector3[] {
//left
new Vector3(0,0,0),
new Vector3(0,height,0),
new Vector3(0,height,-width),
new Vector3(0,0,-width),
//front
new Vector3(0,0,-width),
new Vector3(0,height,-width),
new Vector3(0,height,-width),
new Vector3(0,0,-width),
//right
new Vector3(0,0,-width),
new Vector3(0,height,-width),
new Vector3(0,height,0),
new Vector3(0,0,0),
//back
new Vector3(0,0,0),
new Vector3(0,height,0),
new Vector3(0,height,0),
new Vector3(0,0,0),
//up
new Vector3(0,height,-width),
new Vector3(0,height,0),
new Vector3(0,height,0),
new Vector3(0,height,-width),
//down
new Vector3(0,0,0),
new Vector3(0,0,-width),
new Vector3(0,0,-width),
new Vector3(0,0,0)
};
triangles = new int[] {
//left
0,1,2,
2,3,0,
//front
4,5,6,
6,7,4,
//right
8,9,10,
10,11,8,
//back
12,13,14,
14,15,12,
//up
16,17,18,
18,19,16,
//down
20,21,22,
22,23,20
};
UVs = new Vector2[] {
//left
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
//front
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
//right
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
//back
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
//up
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
//down
new Vector2(0,0),
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
};
mesh.vertices = vertics; //绘制顶点
mesh.triangles = triangles; //绘制三角面
mesh.uv = UVs; //绘制纹理
mesh.RecalculateNormals(); //计算法线
mesh.RecalculateTangents();
mesh.RecalculateBounds();
}
/// <summary>
/// 结束创建自定义模型
/// </summary>
/// <param name="_pos"></param>
private void EndCreateCustomWall(Vector3 _pos)
{
RefreshMeshMod(_pos);
curWall.AddComponent<MeshCollider>();
preLength = length;
preWall = curWall;
preMesh = mesh;
}
/// <summary>
/// 刷新网格
/// </summary>
/// <param name="_pos"></param>
private void RefreshMeshMod(Vector3 _pos)
{
vertics = mesh.vertices;
var vEndCenterX = _pos.x - originPos.x;
var vEndCenterZ = _pos.z - originPos.z;
length = Mathf.Sqrt(vEndCenterX * vEndCenterX + vEndCenterZ * vEndCenterZ);
var vros = _pos - originPos;
curWall.transform.rotation = Quaternion.FromToRotation(Vector3.right, vros);
vertics[6] = new Vector3(length, height, -width);
vertics[7] = new Vector3(length, 0, -width);
vertics[8] = new Vector3(length, 0, -width);
vertics[9] = new Vector3(length, height, -width);
vertics[10] = new Vector3(length, height, 0);
vertics[11] = new Vector3(length, 0, 0);
vertics[12] = new Vector3(length, 0, 0);
vertics[13] = new Vector3(length, height, 0);
vertics[18] = new Vector3(length, height, 0);
vertics[19] = new Vector3(length, height, -width);
vertics[22] = new Vector3(length, 0, -width);
vertics[23] = new Vector3(length, 0, 0);
mesh.vertices = vertics;
mesh.RecalculateNormals();
mesh.RecalculateTangents();
mesh.RecalculateBounds();
RecalculateAngle();
}
/// <summary>
/// 计算接缝处
/// </summary>
private void RecalculateAngle()
{
if (preWall != null)
{
var vrosdis = (curWall.transform.eulerAngles.y - preWall.transform.eulerAngles.y) / 2; //计算两个墙体相交的角度的一半
vrosdis = vrosdis * Mathf.Deg2Rad;
var vbevel = width / Mathf.Cos(vrosdis); //计算相交线
var vx = vbevel * Mathf.Sin(vrosdis);
//print("第一堵墙的角度:" + preObj.transform.eulerAngles.y + " 第二堵墙的角度:" + curObj.transform.eulerAngles.y + " 两堵墙相对角度:" + vrosdis + " 余弦值:" + Mathf.Cos(vrosdis) + " 斜边:" + vbevel + " 正弦值:" + Mathf.Sin(vrosdis) + " 对边:" + vx);
preVertics = preMesh.vertices;
preVertics[6] = new Vector3(preLength - vx, height, -width);
preVertics[7] = new Vector3(preLength - vx, 0, -width);
preVertics[8] = new Vector3(preLength - vx, 0, -width);
preVertics[9] = new Vector3(preLength - vx, height, -width);
preVertics[19] = new Vector3(preLength - vx, height, -width);
preVertics[22] = new Vector3(preLength - vx, 0, -width);
preMesh.vertices = preVertics;
preMesh.RecalculateBounds();
preMesh.RecalculateNormals();
preMesh.RecalculateTangents();
vertics = mesh.vertices;
vertics[2] = new Vector3(vx, height, -width);
vertics[3] = new Vector3(vx, 0, -width);
vertics[4] = new Vector3(vx, 0, -width);
vertics[5] = new Vector3(vx, height, -width);
vertics[16] = new Vector3(vx, height, -width);
vertics[21] = new Vector3(vx, 0, -width);
mesh.vertices = vertics;
mesh.RecalculateNormals();
mesh.RecalculateTangents();
mesh.RecalculateBounds();
}
}
private void OnGUI()
{
if (isStartCreate)
{
var v = Input.mousePosition;
GUIStyle style = new GUIStyle();
style.fontSize = 30;
GUI.Box(new Rect(v.x, Screen.height - v.y - 30, 100, 30), length.ToString("f2") + "米", style);
}
}
}