Unity中UGUI源码剖析之最本质的UI实现原理

一直以来都对Unity中的UGUI比较感兴趣,之前我学过点Android,Android中最让我惊喜就是其中的View 也就是呈现的界面UI,有太多的人发挥着自己的想象力创造了一个又一个酷炫的UI组件;现在学习着Unity中的UGUI,也是希望能造属于自己的轮子,所以了解UGUI源码是必要的,知道这其中最本质UI实现原理也是开始~~

大概的原理

在Unity的世界中,UI的基本组成就是界面和事件,像我们的按钮,有构成按钮的外观以及响应的事件,至此才说得上是个UI。

界面的构成

这里的界面不仅仅只是指2D,同样3D在Unity中也是相同的原理。我们能够在Unity中看到物体其实多亏了下面的这两个

MeshRender以及MeshFilter,有了它们才能让我们看到物体的样子,具体的细节我就不细说,大体就是一个物体模型构成需要网格以及UV贴图(这还是我学建模的时候接触到的,当然远不止这些),这样在导入Unity配合上面两个组件和灯光就能够让我们看到了。

界面的事件

说到事件究其本质应该是射线监测外加行为判断才有的,这让我想起了用Unity做的第一个项目,那时我用的就是射线来处理很多物体的交互,现在想来还是经验不够,完全可以通过委托事件来弄,会简化好多。

自己的UI自己造

说了那么多,其实只要有个像样的例子也就能理解了

首先上代码,也就这一个代码

MyUI.cs

    using UnityEngine;
    using UnityEngine.UI;
    
    public class MyUI : MonoBehaviour {

        //这是个帮助类,具体可以查看官方文档
        VertexHelper vh = new VertexHelper();
        private Mesh mesh;
        public Color color;
        public Texture2D texture2D;
        private MeshFilter meshFilter;
        private MeshRenderer meshRender;
        private MeshCollider meshCollider;
        public Camera cam;
    
        private MeshFilter MeshFilter{
            get{
                if (meshFilter == null)
                    meshFilter = GetComponent<MeshFilter>();
                return meshFilter;
            }
        }
    
        private MeshRenderer MeshRenderer
        {
            get
            {
                if (meshRender == null)
                    meshRender = GetComponent<MeshRenderer>();
                return meshRender;
            }
        }
    
        private MeshCollider MeshCollider
        {
            get
            {
                if (meshCollider == null)
                    meshCollider = GetComponent<MeshCollider>();
                return meshCollider;
            }
        }
        // Use this for initialization
        void Start () {
            //初始化Mesh
            InitMesh();
        }
        
        // Update is called once per frame
        void Update () {
            //通过屏幕鼠标点击点发射射线
            var ray = cam.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            Physics.Raycast(ray, out hitInfo);
            if (hitInfo.collider != null && hitInfo.collider.gameObject != null)
            {
                //被射线射中且鼠标左键单击了产生单击事件
                if (Input.GetMouseButtonDown(0))
                {
                    Debug.Log("鼠标点击了");
                }
            }
            //将颜色传入MeshRender,给UI增添颜色的变化
            MeshRenderer.material.color = color;
            //将UI图片放入UI的MeshRender中
            MeshRenderer.material.mainTexture = texture2D;
        }
    
        void InitMesh()
        {
            //创建一个Mesh
            mesh = new Mesh();
            vh.Clear();
            //对UI界面进行描绘,主要设置顶点和UV,这里是Vector2 当然也可以Vector3
            vh.AddVert(new Vector2(0, 0), color, new Vector2(0, 0));
            vh.AddVert(new Vector2(0, 1), color, new Vector2(0, 1));
            vh.AddVert(new Vector2(1, 1), color, new Vector2(1, 1));
            vh.AddVert(new Vector2(1, 0), color, new Vector2(1, 0));
            //对顶点进行分序连接成三角形
            vh.AddTriangle(0,1,2);
            vh.AddTriangle(2,3,0);
            //将顶点设置填充到mesh中
            vh.FillMesh(mesh);
            //将mesh填充进MeshFilter
            MeshFilter.mesh = mesh;
            //因为需要射线射中这里需要添加碰撞器,且把mesh传入
            MeshCollider.sharedMesh = mesh;
        }
    }

代码挂载到一个空物体上,具体像下面这样

MyUI.png

具体的解释已经在代码中给出了,对了如果对其中的顶点设置有疑问的话可以移步 这里

当然也可以参看原文 here

还有一点我要说的是这并非我原创,我只是把理解写出来而已,详细可以参看 这里

基本实现以及原理说的差不多了,接下来就需要自己去源码中寻找更多的东西,或者之后的某一天我可以写出不同效果的UI出来,那会儿对UGUI的使用才能算熟~

推荐阅读更多精彩内容