Unity中連線
在unity中做連線的功能,有很多中做法。在這里總結一下,可能還有更好的方法,希望有好的方法就提出來共同進步。(說明:主要是拐直角的線的效果,而不是很華麗的線條效果。其實在虛擬現實項目中,這種效果還是經常用到的,比方說室內的電線連接情況等)
第一種:是unity中的輔助線。Gizmos,是用於在scene視圖下可視化調試或輔助設置。這個就不多說了,在api中有詳細介紹。注意的是:所有的繪制需要在OnDrawGizmos或OnDrawGizmosSelected函數里完成。
第二種:是用LineRenderer,是用於在三維空間繪制自由浮動的線。優點就是可以自適應攝像機,就是始終面對着攝像機。但對於多個拐點時就存在斷線的效果的情況,看上去很不舒服,只能每個點的連接需要兩兩連接效果會好點,但是拐點效果就不是很好。如下圖可以直觀說明。
第三種:是用GL,是底層的圖像庫。這個類進行底層的矩陣變換。常用的方法是GL代碼放在OnPostRender()函數里面。這里講的是如何畫線,所以對於GL畫線來說,不好的地方在於線條太細,無法調整線的粗細。我用GL舉個例子!
代碼如下:
View Code
1 using UnityEngine; 2 using System.Collections; 3 4 public class NewBehaviourScript : MonoBehaviour { 5 6 ArrayList lines=new ArrayList(); 7 // Use this for initialization 8 void Start () { 9 MeshFilter meshfilter=GetComponent("MeshFilter") as MeshFilter; 10 Mesh mesh=meshfilter.sharedMesh; 11 Vector3[] vertices=mesh.vertices; 12 int[] triangles=mesh.triangles; 13 for(int i=0;i<triangles.Length/3;i++) 14 { 15 lines.Add(vertices[triangles[i]]); 16 lines.Add(vertices[triangles[i*3+1]]); 17 lines.Add(vertices[triangles[i*3+2]]); 18 } 19 } 20 void OnRenderObject() 21 { 22 if (true) 23 { 24 GL.PushMatrix(); 25 GL.MultMatrix(transform.localToWorldMatrix); 26 GL.Begin(GL.LINES); 27 GL.Color(Color.blue); 28 for (int i = 0; i < lines.Count / 3; i++) 29 { 30 GL.Vertex((Vector3)lines[i * 3]); 31 GL.Vertex((Vector3)lines[i * 3 + 1]); 32 GL.Vertex((Vector3)lines[i * 3 + 1]); 33 GL.Vertex((Vector3)lines[i * 3 + 2]); 34 GL.Vertex((Vector3)lines[i * 3 + 2]); 35 GL.Vertex((Vector3)lines[i * 3]); 36 } 37 GL.End(); 38 GL.PopMatrix(); 39 } 40 } 41 42 }
解釋一下代碼:
第一步,獲取模型的所有頂點!
MeshFilter meshfilter=GetComponent("MeshFilter") as MeshFilter;//查找MeshFilter組建
Mesh mesh=meshfilter.sharedMesh;//獲取mesh
Vector3[] vertices=mesh.vertices;//獲取模型的所有頂點
int[] triangles=mesh.triangles;//三角形的所有頂點的索引(索引是在模型頂點數組的索引)
for(int i=0;i<triangles.Length;i++) //有triangles.Length/3個三角形
{
lines.Add(vertices[triangles[i]]);
}
第二步:繪制模型的頂點之間的網格線
繪制模型的網格線,就是繪制每個三角形的三條邊,第一步已經把所有的三角形的邊找出來了
,下面就開始繪制了,用GL繪制,那么就必須使用OnRenderObject()方法,
void OnRenderObject()
{
GL.PushMatrix();//壓入矩陣
/*使用了transform.localToWorldMatrix這個矩陣,上面的頂點沒有進行變換的,還是本地坐標的,在這兒做了轉換!大家要注意的是 transform.localToWorldMatrix變換一個本地坐標的話,那么transform.position並沒有參與變換頂點的工作!在DX和OPENGL中,localToWorldMatrix,那么物體的position都會參加變換的,這一點u3d做的不一樣,呵呵!
我說的沒有參與變換頂點的工作,是什么意思呢?
下面我舉個例子!
transform.localToWorldMatrix*Vector3.forward那么在其它的程序中,是transform.position加上transform的旋轉和縮放對Vector3.forward變換后的值,但是u3d卻沒有這樣做!u3d中transform.localToWorldMatrix*Vector3.forward是用旋轉和縮放對Vector3.forwad做了變換!*/
//在下面的這一句中明確的告訴大家,transform.position參加了變換!
GL.MultMatrix(transform.localToWorldMatrix);
//用線條進行繪制
GL.Begin(GL.LINES);
//用藍色進行繪制
GL.Color(Color.blue);
//繪制線,兩個點組成一條線段
for (int i = 0; i < lines.Count / 3; i++)
{
GL.Vertex((Vector3)lines[i * 3]);
GL.Vertex((Vector3)lines[i * 3 + 1]);
GL.Vertex((Vector3)lines[i * 3 + 1]);
GL.Vertex((Vector3)lines[i * 3 + 2]);
GL.Vertex((Vector3)lines[i * 3 + 2]);
GL.Vertex((Vector3)lines[i * 3]);
}
//繪制結束
GL.End();
//拋出剛才壓入的矩陣
GL.PopMatrix();
}
第四種:運用Sphere球體和Cylinder圓柱,通過控制縮放來畫線,Sphere處理拐點,使其美觀。


View Code
1 using UnityEngine; 2 using System.Collections; 3 using System.Collections.Generic; 4 5 public class DrawLineEX : MonoBehaviour 6 { 7 GameObject line; 8 GameObject corner; 9 Vector3[] wayPoint; 10 GameObject[] go; 11 GameObject lineClone; 12 13 float offsetScaleH = 0.0f; 14 float scaleValue; 15 float offsetScaleV = 0.005f; 16 17 public Transform port1; 18 public Transform port2; 19 20 public void Start() 21 { 22 scaleValue = 0.2f; 23 wayPoint = new Vector3[0]; 24 go = new GameObject[0]; 25 lineClone = new GameObject(); 26 line = (GameObject)Resources.Load("Prefab/Line/Line"); 27 corner = (GameObject)Resources.Load("Prefab/Line/Corner"); 28 29 DrawDifLine(port1,port2,1,1,Color.blue); 30 LineRendererFunc(); 31 } 32 33 //算了7個點,這個可以根據需求來改動自己所需要經過的點。portState參數是用來改變方向的 34 void DrawDifLine(Transform Selectpoint, Transform Mathpoint, float portState1, float portState2, Color color) 35 { 36 wayPoint = new Vector3[7]; 37 wayPoint[0] = Selectpoint.position; 38 39 wayPoint[6] = Mathpoint.position; 40 41 Vector3 position1 = Selectpoint.TransformPoint(new Vector3(0, 0f, 3f * portState1)); 42 wayPoint[1] = position1; 43 44 float y1 = Selectpoint.position.y + 2f; 45 Vector3 position2 = new Vector3(position1.x, y1, position1.z); 46 wayPoint[2] = position2; 47 48 Vector3 position3 = Mathpoint.TransformPoint(new Vector3(0, 0f, 3f * portState2)); 49 wayPoint[5] = position3; 50 51 float y2 = Selectpoint.position.y + 2f; 52 Vector3 position4 = new Vector3(position3.x, y2, position3.z); 53 wayPoint[4] = position4; 54 55 Vector3 position5 = new Vector3(position4.x, y2, position2.z); 56 wayPoint[3] = position5; 57 58 DL(color, scaleValue); 59 } 60 61 //主要的畫法。 62 void DL(Color lineColor, float lineSize) 63 { 64 go = new GameObject[(2 * wayPoint.Length - 3)]; 65 int j; 66 //draw line 67 Vector3 centerPos = Vector3.zero; 68 for (j = 0; j < wayPoint.Length - 1; j++) 69 { 70 centerPos = (wayPoint[j] + wayPoint[j + 1]) / 2; 71 go[j] = (GameObject)Instantiate(line, centerPos, transform.localRotation); 72 go[j].renderer.material.color = lineColor; 73 74 go[j].transform.parent = lineClone.transform; 75 go[j].name = "Line" + j + 1; 76 go[j].transform.up = (go[j].transform.localPosition - wayPoint[j]).normalized; 77 float distance = Vector3.Distance(wayPoint[j], wayPoint[j + 1]); 78 go[j].transform.localScale = new Vector3(lineSize, distance / 2 + offsetScaleH, lineSize); 79 } 80 81 //draw port 82 for (int i = 1; i < wayPoint.Length - 1; i++) 83 { 84 centerPos = wayPoint[i]; 85 go[j + i - 1] = (GameObject)Instantiate(corner, centerPos, transform.localRotation); 86 go[j + i - 1].renderer.material.color = lineColor; 87 88 go[j + i - 1].name = "Port" + i; 89 go[j + i - 1].transform.parent = lineClone.transform; 90 go[j + i - 1].transform.localScale = new Vector3(lineSize, lineSize, lineSize); 91 } 92 } 93 94 //GL 95 public Material mat; 96 void OnPostRender() { 97 if (!mat) { 98 Debug.LogError("Please Assign a material on the inspector"); 99 return; 100 } 101 GL.PushMatrix(); 102 mat.SetPass(0); 103 GL.LoadOrtho(); 104 GL.Begin(GL.LINES); 105 GL.Color(Color.red); 106 GL.Vertex(Vector3.zero); 107 GL.Vertex(Vector3.one); 108 GL.End(); 109 GL.PopMatrix(); 110 } 111 112 //LineRenderer 113 void LineRendererFunc() 114 { 115 GameObject obj = new GameObject(); 116 LineRenderer lineRenderer; 117 lineRenderer = obj.AddComponent<LineRenderer>(); 118 lineRenderer.useWorldSpace = false;//是否使用世界坐標,true的話,自身坐標將被忽略。 119 lineRenderer.material = new Material(Shader.Find("Particles/Additive")); 120 lineRenderer.SetColors(Color.red, Color.yellow);//設置顏色,一個是起始和終止顏色。 121 lineRenderer.SetVertexCount(7);//設置線段數量,可以根據需求來動態改變,靈活改變。 122 123 for (int i = 0; i < wayPoint.Length; i++) 124 { 125 lineRenderer.SetPosition(i, wayPoint[i]); 126 } 127 } 128 129 }
代碼如下:對代碼中主要部分做了解釋,如果有不明白的可以留言或者在api中查到。
第五種:用Vectrosity插件,這個插件是基於lineRenderer的,是一個很好的插件對於畫線來說。后續中。。。。。
源碼:http://www.cnblogs.com/alongu3d/admin/Files.aspx
如有不對的地方,還請指教,呵呵!
