問題分析:
最近在搞軟件底層開發,將一些工具或者底層腳本打成dll導入unity使用,有這樣一需求,就是編輯功能,需要像Scene場景一樣,實現那種編輯軸
實現方式:
創建Mesh,構建編輯軸,這個地方這么幾步:
1.線(軸)
2.圓(旋轉線)
3.正方形(軸面)
4.圓錐(軸方向)
具體步驟:
1.創建線Mesh:
代碼:
/// <summary> /// 創建線Mesh /// </summary> /// <param name="start">線起點</param> /// <param name="end">線終點</param> /// <returns>Mesh對象</returns> private Mesh CreateLineMesh(Vector3 start, Vector3 end) { var vertices = new List<Vector3> { start, end }; var indices = new List<int> { 0, 1 }; Mesh mesh = new Mesh(); mesh.SetVertices(vertices); mesh.SetIndices(indices.ToArray(), MeshTopology.Lines, 0); return mesh; }
這就創建一條起點為start,終點為end的線,是這樣,這里在創建是通過Mesh的拓撲結構MeshTopology實現的,MeshTopology是一個枚舉,
使用SetIndices去賦值索引,參數分別是索引數組,選擇的拓撲結構,要修改的子網格,還有兩種重載自己去查。
2.創建圓Mesh:
代碼:
/// <summary> /// 創建(旋轉)圓圈Mesh /// </summary> /// <param name="radius">圓圈半徑</param> /// <returns></returns> private Mesh CreateCircleMesh(float radius) { List<Vector3> vertexList = new List<Vector3>(); List<int> indexList = new List<int>(); for (float i = 0; i < 360.0f; i += 5.0f) { float rad = Mathf.Deg2Rad * i; float cosA = Mathf.Cos(rad); float sinA = Mathf.Sin(rad); vertexList.Add(new Vector3(radius * cosA, radius * sinA, 0)); if (i != 0) { vertexList.Add(new Vector3(radius * cosA, radius * sinA, 0)); } } vertexList.Add(new Vector3(radius * Mathf.Cos(Mathf.Deg2Rad * 0), radius * Mathf.Sin(Mathf.Deg2Rad * 0), 0)); for (int i = 0; i < 144; i++) { indexList.Add(i); } Mesh mesh = new Mesh(); mesh.SetVertices(vertexList); mesh.SetIndices(indexList.ToArray(), MeshTopology.Lines, 0); return mesh; }
代碼中144=(360/5)*2(端點相連問題)
當時這里的實現思路我想了三種:
1.使用Mesh,自己創建圓面(倆圓面創建出圓圈)
2.LineRender畫圓
3.使用Mesh,創建拓撲結構線畫圓圈
說一下我為什么選擇最后一種:
首先我選的第一種方式,畫出來沒問題,但是有一種情況,因為圓是在旋轉時用的,旋轉線需要旋轉,當圓旋轉到與你成90度時,你就看不到線了。因為這是一面啊,垂直於你指定接近看不着了。
其次呢,我在想讓在任何角度看到他都是一根線一個線圓,所以我想到了LineRender畫線,畫圓,這次畫的很好,實現了想要的效果,但是又出現了問題,就是這都是軸,我需要加碰撞器,我需要拾取處理相應操作,但是我查閱了一下,反正有說可以的,但是我試了一圈不行(我沒加上碰撞器,加上有問題,自己踩吧你們),所以最后使用的是拓撲結構線插值出一個圓。我成功了完美實現。
這里加上我的另兩種嘗試代碼:
//private LineRenderer line; //private int r = 20; //private int n = 360; ///lineRender畫圓 //void Start() //{ // line = this.GetComponent<LineRenderer>(); // line.positionCount = 360 + 1; // for (int i = 0; i < n + 1; i++) // { // //划線的話2D坐標就行了,這里我們計算x和z坐標軸上的坐標,而y永遠是0 // //計算x和z的長度,乘以半徑r來得到最終長度 // float x = Mathf.Cos((360 * (i + 1) / n) * Mathf.Deg2Rad) * r; // float z = Mathf.Sin((360 * (i + 1) / n) * Mathf.Deg2Rad) * r; // //設置坐標畫線 // line.SetPosition(i, new Vector3(0, x, z)); // } //}
/// <summary> /// 使用Mesh畫兩個圓面組成的圓環 /// </summary> /// <param name="radius"></param> /// <param name="innerradius"></param> /// <param name="angledegree"></param> /// <param name="segments"></param> /// <returns></returns> Mesh CreateMesh(float radius, float innerradius, float angledegree, int segments) { //vertices(頂點): int vertices_count = segments * 2 + 2; //因為vertices(頂點)的個數與triangles(索引三角形頂點數)必須匹配 Vector3[] vertices = new Vector3[vertices_count]; float angleRad = Mathf.Deg2Rad * angledegree; float angleCur = angleRad; float angledelta = angleRad / segments; for (int i = 0; i < vertices_count; i += 2) { float cosA = Mathf.Cos(angleCur); float sinA = Mathf.Sin(angleCur); vertices[i] = new Vector3(radius * cosA, 0, radius * sinA); vertices[i + 1] = new Vector3(innerradius * cosA, 0, innerradius * sinA); angleCur -= angledelta; } //triangles: int triangle_count = segments * 6; int[] triangles = new int[triangle_count]; for (int i = 0, vi = 0; i < triangle_count; i += 6, vi += 2) { triangles[i] = vi; triangles[i + 1] = vi + 3; triangles[i + 2] = vi + 1; triangles[i + 3] = vi + 2; triangles[i + 4] = vi + 3; triangles[i + 5] = vi; } //負載屬性與mesh Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; //mesh.uv = uvs; mesh.RecalculateNormals(); return mesh; }
3.創建正方形Mesh:
代碼:
/// <summary> /// 創建正方形面Mesh /// </summary> /// <param name="size">面尺寸</param> /// <returns>Mesh對象</returns> private Mesh CreatePlaneMesh(Vector2 size) { var vertices = new List<Vector3>(); var indices = new List<int>(); var x = size.x * 0.5f; var z = size.y * 0.5f; vertices.Add(new Vector3(x, 0.0f, z)); vertices.Add(new Vector3(-x, 0.0f, z)); vertices.Add(new Vector3(-x, 0.0f, -z)); vertices.Add(new Vector3(x, 0.0f, -z)); indices.Add(0); indices.Add(1); indices.Add(2); indices.Add(0); indices.Add(2); indices.Add(3); Mesh mesh = new Mesh(); mesh.SetVertices(vertices); mesh.SetTriangles(indices, 0); mesh.RecalculateNormals(); return mesh; }
這個就不說啥了,前面說過創建立方體了。
4.創建圓錐Mesh
代碼:
/// <summary> /// 創建圓錐Mesh /// </summary> /// <param name="radius">圓錐底面半徑</param> /// <param name="height">圓錐高度</param> /// <returns>Mesh對象</returns> private Mesh CreateConeMesh(float radius, float height) { var vertices = new List<Vector3>(); var indices = new List<int>(); vertices.Add(Vector3.zero); vertices.Add(Vector3.up * height); var temp = new List<Vector3>(); //底圓面 for (var i = 0.0f; i < 360.0f; i += 30) { var rad = Mathf.Deg2Rad * i; var x = radius * Mathf.Cos(rad); var z = radius * Mathf.Sin(rad); temp.Add(new Vector3(x, 0.0f, z)); } vertices.AddRange(temp); vertices.AddRange(temp); for (var i = 2; i <= 13; i++) { indices.Add(i); if (i < 13) { indices.Add(i + 1); } else { indices.Add(2); } indices.Add(0); } for (var i = 14; i <= 25; i++) { indices.Add(i); indices.Add(1); if (i < 25) { indices.Add(i + 1); } else { indices.Add(14); } } Mesh mesh = new Mesh(); mesh.SetVertices(vertices); mesh.SetTriangles(indices, 0); mesh.RecalculateNormals(); return mesh; }
到這就需要的編輯軸物件都創建完成了。
效果圖: