• Unity中连线


                                                       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

    如有不对的地方,还请指教,呵呵!

  • 相关阅读:
    flutter资料
    flutter兼论
    Dart 学习
    flutter简易教程
    全球15个顶级技术类博客
    Grunt压缩HTML和CSS
    用grunt搭建自动化的web前端开发环境-完整教程
    正确代码之-grunt
    grunt写一个px和rem互转的工具
    unslider使用方法1
  • 原文地址:https://www.cnblogs.com/alongu3d/p/2872364.html
Copyright © 2020-2023  润新知