• 您的位置:首页 > 新闻动态 > Unity3D

    unity3d中利用网格+贴图绘制血条/进度条

    2019/11/1      点击:

    利用网格去绘制血条, 血条肯定是一个矩形,网格是由一个一个三角形组成的,矩形可以分成两个三角形。
    创建一个空物体,添加以下脚本组件:

    [RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
    public class MeshAndUV : MonoBehaviour
    {
     
        private Mesh mh;
        private Renderer rd;
        private float size = 1;
        private Material mat;
        void Awake()
        {
            mh = GetComponent().mesh;
            rd = GetComponent();
        }
     
        void Start()
        {
     
           //顶点数组
            Vector3[] vertes  = new Vector3[]
            {
                new Vector3(-size, -size, 0),//第一个点
                new Vector3(-size, size, 0), //第二个
                new Vector3(size, size, 0), //第三个
                new Vector3(size, -size, 0), //第四个
            };
     
            mh.vertices = vertes;
     
            //顶点组成的三角形
            mh.triangles = new[]
            {
                0, 1, 2,
                0, 2, 3
            };
            mh.RecalculateNormals();
        }
    }
    运行下,就发现绘制出一个粉红色的矩形,为啥是粉红色,因为没材质啊!!!@#¥%@#¥……

    在scene视图下把ShadingMode改为Wireframe模式就可以看到两个三角形

    轴点在中心,边长为2的矩形,然后在脚本上设置UV映射,加上贴图材质。

    在设置三角形下面添加一下代码就可以显示纹理了呀:

    //UV贴图的四个点,和顶点一一对应,左下角为(0,0),右上角为(1,1)
    //如果顶点顺序没有跟UV对应,贴图就会出现问题
    Vector2[] uvs = new Vector2[]
    {
        new Vector2(0,0),//第一个点
        new Vector2(0,1),//2
         new Vector2(1,1),//3
         new Vector2(1,0), //4
    };
    
     mh.uv = uvs;
     rd.material = mat;


    封装成一个函数 void CreateBar(int barIndex),修改UV映射,血条索引从下往上数,每个间隔0.25f

    Vector2[] uvs = new Vector2[]
    {
         new Vector2(0, 0.25f * barIndex),//第一个点
         new Vector2(0, 0.25f * (barIndex+1)),//2
         new Vector2(1, 0.25f * (barIndex+1)),//3
         new Vector2(1, 0.25f * barIndex), //4
    };
    在Start方法调用 CreateBar(0),呀, 怎么红色是满的呢?

    由于满血状态是全红的,所以在UV的x映射也要做下改变

    Vector2[] uvs = new Vector2[]
    {
         new Vector2(0, 0.25f * barIndex),//第一个点
         new Vector2(0, 0.25f * (barIndex+1)),//2
         new Vector2(0.5f, 0.25f * (barIndex+1)),//3
         new Vector2(0.5f, 0.25f * barIndex), //4
    };

    是不是有点像啦。只要改变下长宽比就好看啦。 改成下面这样多一个参数试试看。


    void CreateBar(Vector2 size, int barIndex)
    {
        Vector3[] vertes = new Vector3[]
            {
                new Vector3(-size.x, -size.y, 0),//第一个点
                new Vector3(-size.x, size.y, 0), //第二个
                new Vector3(size.x, size.y, 0), //第三个
                new Vector3(size.x, -size.y, 0), //第四个
            };
    }
    看看血条效果吧:



    改变血条的值有2个办法,
    1.改变Material的mainTextureOffset值
    mat.mainTextureOffset = new Vector2(0.2f,0);

    但是这样会令到所以使用者材质的物体贴图都会改变
    2.修改UV映射


    void SetBarRate(float value)
        {
            value *= 0.5f;
            Vector2[] uvs = new Vector2[]
            {
                new Vector2(value, 0.25f * barIndex),//第一个点
                new Vector2(value, 0.25f * (barIndex+1)),//2
                new Vector2(0.5f + value , 0.25f * (barIndex+1)),//3
                new Vector2(0.5f + value, 0.25f * barIndex), //4
            };
            mh.uv = uvs;
        }
    //因为这张图一半是亮的,一半是暗的,暗的那部分代表失去的血量,所以value要乘以0.5;
    void Start()
        {
            CreateBar(new Vector2(1,0.25f),0 );
            SetBarRate(0.9f);
        }
    到此基本完成了任务, 下面来个完整的代码给各位亲参考一下, 欢迎来我们网站wiseglove.com投稿哦~



    using UnityEngine;
    using System.Collections;
     
    [RequireComponent(typeof(MeshFilter),typeof(MeshRenderer))]
    public class MeshAndUV : MonoBehaviour
    {
        private Mesh mh;
        private Renderer rd;
        
        private float rate = 0.5f;
        public Material mat;
     
        private int barIndex = 0;
        void Awake()
        {
            mh = GetComponent().mesh;
            rd = GetComponent();
           
        }
        void Start()
        {
            CreateBar(new Vector2(1,0.25f),0 );
            SetBarRate(0.9f);
        }
        ////// 利用网格创建血条
        //////三角形大小///血条索引void CreateBar(Vector2 size, int barIndex)
        {
            this.barIndex = barIndex;
            //顶点数组
            Vector3[] vertes = new Vector3[]
            {
                new Vector3(-size.x, -size.y, 0),//第一个点
                new Vector3(-size.x, size.y, 0), //第二个
                new Vector3(size.x, size.y, 0), //第三个
                new Vector3(size.x, -size.y, 0), //第四个
            };
            //给网格的顶点赋值
            mh.vertices = vertes;
     
            //顶点组成的三角形
            mh.triangles = new[]
            {
                0, 1, 2,
                0, 2, 3
            };
     
            //UV贴图的四个点,和顶点一一对应,左下角为(0,0),右上角为(1,1)
            //如果顶点顺序没有跟UV对应,贴图就会出现问题
            Vector2[] uvs = new Vector2[]
            {
                new Vector2(0, 0.25f * barIndex),//第一个点
                new Vector2(0, 0.25f * (barIndex+1)),//2
                new Vector2(0.5f , 0.25f * (barIndex+1)),//3
                new Vector2(0.5f , 0.25f * barIndex), //4
            };
            mh.uv = uvs;
            //材质
            rd.material = mat;
            //法线重新计算
            mh.RecalculateNormals();
        }
        ////// 设置血条比例
        //////血量失去的百分比void SetBarRate(float value)
        {
            value *= 0.5f;
            Vector2[] uvs = new Vector2[]
            {
                new Vector2(value, 0.25f * barIndex),//第一个点
                new Vector2(value, 0.25f * (barIndex+1)),//2
                new Vector2(0.5f + value , 0.25f * (barIndex+1)),//3
                new Vector2(0.5f + value, 0.25f * barIndex), //4
            };
            mh.uv = uvs;
        }
    }
    按照上面的方法, 画进度条也是这个方法。