使用VertexHelper自定义控件之ColorBar(二)

一、实现ColorBar

什么是ColorBar???直接上效果图:
在这里插入图片描述

就是一组数据映射到一组颜色上,类似于伪彩图。首先我们需要准备一组颜色,我们可以选择HSV颜色模型,HSV颜色模型在这不做详细解释,不了解的同学可以自行学习。

那么如何将颜色填充到顶点上呢?我们可以用矩形顶点,矩形上面两个顶点用同一个颜色,矩形下面两个顶点用其他的同一个颜色,这个矩形下面的两个顶点会和下一个矩形的上面两个顶点重合。

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();

        var count = 15;//定义矩形的个数,个数越多颜色越精细,但是算力也会越大。对应的颜色值则会+1.
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (1f - 0f) / count;//在0-1中间插值count-1个 则一共有count+1个颜色值
        //当然,你也可以不需要h在0-1的范围 可自行修改最大值和最小值。

        for (int i = 0; i < count; i++)
        {
            UIVertex[] verts = new UIVertex[4];
            verts[0].position = new Vector3(rect.xMin, rect.yMin + i * posStep);
            verts[0].color = HSVToRGB(i * colorStep);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, rect.yMin + i * posStep);
            verts[1].color = HSVToRGB(i * colorStep);
            verts[1].uv0 = Vector2.zero;

            verts[2].position = new Vector3(rect.xMax, rect.yMin + (i + 1) * posStep);
            verts[2].color = HSVToRGB((i + 1) * colorStep);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin, rect.yMin + (i + 1) * posStep);
            verts[3].color = HSVToRGB((i + 1) * colorStep);
            verts[3].uv0 = Vector2.zero;

            vh.AddUIVertexQuad(verts);
        }
    }

在这里插入图片描述

接下来我们要给颜色加上刻度线。为了给刻度线在左侧预留一个位置,我们在设置顶点位置的时候不能设置为xMin,所以我们改成这样:

public class CreateRectangle : Graphic
{
    int count = 15;//定义矩形的个数,个数越多颜色越精细,但是算力也会越大。对应的颜色值则会+1.
    float hMin = 0;
    float hMax = 1;
    float leftMargin = 60;

    protected override void Start()
    {
        base.Start();
        StartCoroutine(MUpdateGeometry());
    }

    IEnumerator MUpdateGeometry()
    {
        while (true)
        {
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (hMax - hMin) / count;//在0-1中间插值count-1个 则一共有count+1个颜色值
        //当然,你也可以不需要h在0-1的范围 可自行修改最大值和最小值。

        for (int i = 0; i < count; i++)
        {
            UIVertex[] verts = new UIVertex[4];
            verts[0].position = new Vector3(rect.xMin + leftMargin, rect.yMin + i * posStep);
            verts[0].color = HSVToRGB(i * colorStep);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, rect.yMin + i * posStep);
            verts[1].color = HSVToRGB(i * colorStep);
            verts[1].uv0 = Vector2.zero;

            verts[2].position = new Vector3(rect.xMax, rect.yMin + (i + 1) * posStep);
            verts[2].color = HSVToRGB((i + 1) * colorStep);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin + leftMargin, rect.yMin + (i + 1) * posStep);
            verts[3].color = HSVToRGB((i + 1) * colorStep);
            verts[3].uv0 = Vector2.zero;

            vh.AddUIVertexQuad(verts);
        }
    }
}

在这里插入图片描述

刻度线我们会使用一个Text放在左侧,所以我们创建了一个预制体:

在这里插入图片描述

这个预制体的Width我们会设置为刚才预留的位置的宽度,高度就不改变了,然后PosX可以算出来固定不变,根据实际的位置计算得到PosY即可。

public class CreateRectangle : Graphic
{
    int count = 15;//定义矩形的个数,个数越多颜色越精细,但是算力也会越大。对应的颜色值则会+1.
    float hMin = 0;
    float hMax = 1;
    float leftMargin = 60;
    float markMax = 6000;
    float markMin = 0;
    GameObject markTextPrefab;

    protected override void Start()
    {
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
        StartCoroutine(MUpdateGeometry());
    }

    IEnumerator MUpdateGeometry()
    {
        while (true)
        {
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    private GameObject InitMarkTextPrefab()
    {
        var prefab = (GameObject)Resources.Load("MarkText", typeof(GameObject));

        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - leftMargin / 2;

        prefab.GetComponent<RectTransform>().rect.Set(-x, 0, leftMargin, 20);
        return prefab;
    }

    private void CreateOneMarkText(float yPos, string msg, string name)
    {
        var markText = (GameObject)Instantiate(markTextPrefab);
        markText.name = "MarkText" + name;
        markText.transform.SetParent(this.transform);
        var originRect = markText.GetComponent<RectTransform>().rect;
        markText.GetComponent<RectTransform>().rect.Set(originRect.x, yPos, originRect.width, originRect.height);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="h">0-1</param>
    /// <param name="s">0-1</param>
    /// <param name="v">0-1</param>
    /// <returns></returns>
    private Color HSVToRGB(float h)
    {
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        var posStep = (rect.yMax - rect.yMin) / count;
        var colorStep = (hMax - hMin) / count;//在0-1中间插值count-1个 则一共有count+1个颜色值
        //当然,你也可以不需要h在0-1的范围 可自行修改最大值和最小值。

        var markStep = (markMax - markMin) / count;

        for (int i = 0; i < count; i++)
        {
            UIVertex[] verts = new UIVertex[4];
            var y0 = rect.yMin + i * posStep;
            var h0 = i * colorStep;
            verts[0].position = new Vector3(rect.xMin + leftMargin, y0);
            verts[0].color = HSVToRGB(h0);
            verts[0].uv0 = Vector2.zero;

            verts[1].position = new Vector3(rect.xMax, y0);
            verts[1].color = HSVToRGB(h0);
            verts[1].uv0 = Vector2.zero;
            CreateOneMarkText(y0, (i * markStep).ToString(), i.ToString());

            var y1 = y0 + posStep;
            var h1 = h0 + colorStep;
            verts[2].position = new Vector3(rect.xMax, y1);
            verts[2].color = HSVToRGB(h1);
            verts[2].uv0 = Vector2.zero;

            verts[3].position = new Vector3(rect.xMin + leftMargin, y1);
            verts[3].color = HSVToRGB(h1);
            verts[3].uv0 = Vector2.zero;
            CreateOneMarkText(y1, ((i + 1) * markStep).ToString(), (i + 1).ToString());

            vh.AddUIVertexQuad(verts);
        }
    }
}

但是,出问题了!!!

Trying to add MarkText15 (UnityEngine.UI.Text) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.

这是因为:实例化一个UI控件时调用了graphic rebuild操作,而OnPopulateMesh(),函数是在graphic rebuild操作中被调用的,所以若在OnPopulateMesh(), 中创建一个新的UI控件时系统会提示错误:graphic rebuild操作被循环调用了,所以这里需要使用协程操作(IEnumerator),在进入协程操作后,必须立即执行yield return new WaitForSeconds(0),使当前协程暂时退出,让graphic rebuild操作先执行。

所以我们需要将CreateOneMarkText修改为协程:

    IEnumerator CreateOneMarkText(float yPos, string msg, string name)
    {
        yield return new WaitForSeconds(0);
        name = "MarkText" + name;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - leftMargin / 2;
        markText.GetComponent<RectTransform>().anchoredPosition = new Vector2(-x, yPos);
        markText.GetComponent<Text>().text = msg + "-";
    }

然后再调用的地方修改为:

StartCoroutine(CreateOneMarkText(y0, (i * markStep).ToString(), i.ToString()));

在这里插入图片描述

二、添加单位

上面完成后你会发现个问题,最底部和最顶部的刻度信息是超出控件大小的,所以我们也需要留一个余量,然后还需要考虑单位放置的位置。还需要给ColorBar添加一个背景,完整代码如下:

public class ColorBar : Graphic
{
    public Color MarkTextColor;
    public int UIVertexQuadCount = 15;//定义矩形的个数,个数越多颜色越精细,但是算力也会越大。对应的颜色值则会+1.
    float hMin = 0;
    float hMax = 1;
    public float MarkTextWidth = 40;
    public float MarkTextHeight = 16;
    float markMax = 6000;
    float markMin = 0;
    GameObject markTextPrefab;

    protected override void Start()
    {
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
    }

    IEnumerator MUpdateGeometry()
    {
        while (true)
        {
            UpdateGeometry();
            //SetVerticesDirty();
            yield return new WaitForSeconds(2);
        }
    }

    private GameObject InitMarkTextPrefab()
    {
        var game = (GameObject)Resources.Load("MarkText", typeof(GameObject));
        return game;
    }

    IEnumerator CreateOneMarkText(float yPos, string msg, string name)
    {
        yield return new WaitForSeconds(0);
        name = "MarkText" + name;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - MarkTextWidth / 2;
        markText.GetComponent<RectTransform>().sizeDelta = new Vector2(MarkTextWidth, MarkTextHeight);
        markText.GetComponent<RectTransform>().anchoredPosition = new Vector2(-x, yPos);
        markText.GetComponent<Text>().text = msg;
        markText.GetComponent<Text>().color = MarkTextColor;
    }

    private Color CreateOneColor(float h)
    {
        return Color.HSVToRGB(h, 1, 1);
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        float yMax, yMin;
        yMax = rect.yMax - MarkTextHeight / 2;
        //是因为底部需要预留单位信息,所以多加了一个空间。
        yMin = rect.yMin + MarkTextHeight / 2 + MarkTextHeight / 2;

        var posStep = (yMax - yMin) / UIVertexQuadCount;
        var colorStep = (hMax - hMin) / UIVertexQuadCount;//中间插值count-1个 则一共有count+1个颜色值

        var markStep = (markMax - markMin) / UIVertexQuadCount;

        //添加单位
        StartCoroutine(CreateOneMarkText(yMin - MarkTextHeight / 2, "mm", "unit"));

        for (int i = 0; i < UIVertexQuadCount; i++)
        {
            UIVertex[] verts = new UIVertex[4];
            var y0 = yMin + i * posStep;
            var h0 = hMin + i * colorStep;
            verts[0] = CreateOneUIVertex(new Vector2(rect.xMin + MarkTextWidth, y0), h0);
            verts[1] = CreateOneUIVertex(new Vector2(rect.xMax, y0), h0);

            var m0 = markMin + (i * markStep);
            StartCoroutine(CreateOneMarkText(y0, m0.ToString() + "-", i.ToString()));

            var y1 = y0 + posStep;
            var h1 = h0 + colorStep;
            verts[2] = CreateOneUIVertex(new Vector2(rect.xMax, y1), h1);
            verts[3] = CreateOneUIVertex(new Vector2(rect.xMin + MarkTextWidth, y1), h1);

            var m1 = m0 + markStep;
            StartCoroutine(CreateOneMarkText(y1, m1.ToString() + "-", (i + 1).ToString()));

            vh.AddUIVertexQuad(verts);
        }
    }

    private UIVertex CreateOneUIVertex(Vector2 pos, float h)
    {
        UIVertex vert = new UIVertex();
        vert.position = new Vector3(pos.x, pos.y);
        vert.color = CreateOneColor(h);
        vert.uv0 = Vector2.zero;

        return vert;
    }
}

在这里插入图片描述

三、反思

上面添加单位后似乎就完结了???不,其实上面我们犯了一个错,那就是我们先画了颜色带,然后添加了刻度线,这里怎么会错呢?因为刻度线的数量不是固定的,在控件大小发生变化的时候会也需要刻度线做相应的变化。所以,我们重新梳理一下:

  1. 我们首先有一个值和颜色的映射关系
  2. 我们将取值范围线性平铺在界面上(坐标轴),坐标轴的创建过程大致为:根据一个坐标刻度的高度和坐标轴的高度计算刻度的个数,然后再与坐标轴范围计算刻度步长。
  3. 创建好坐标轴后再根据值和颜色的映射关系画出颜色带(画几个颜色取决于刻度数量)

所以,我们的代码又改动了很多:

public class ColorBar : Graphic
{
    public int UIVertexQuadNumBetweenTwoMarkText = 3;
    const string MarkTextNameBase = "MarkText";
    public string unit = "unknown";
    readonly float[] MarkTabs = new float[] { 1, 2, 5 };
    public Color MarkTextColor = Color.white;
    public float MarkTextWidth = 40;
    public float MarkTextHeight = 16;
    private float markTextMax = 6200;
    public Func<float, float, float, Color> CalcOneColor;
    public float MarkTextMax
    {
        get { return markTextMax; }
        set
        {
            if (value > markTextMin)
            {
                markTextMax = value;
                UpdateGeometry();//调用OnPopulateMesh
            }
        }
    }
    private float markTextMin = 100;
    public float MarkTextMin
    {
        get { return markTextMin; }
        set
        {
            if (value < markTextMax)
            {
                markTextMin = value;
                UpdateGeometry();//调用OnPopulateMesh
            }
        }
    }

    GameObject markTextPrefab;

    protected override void Start()
    {
        base.Start();
        markTextPrefab = InitMarkTextPrefab();
    }

    private GameObject InitMarkTextPrefab()
    {
        var game = (GameObject)Resources.Load("MarkText", typeof(GameObject));
        return game;
    }

    void CreateOneMarkText(float yPos, string msg)
    {
        string name = MarkTextNameBase + msg;
        var markText = this.transform.Find(name)?.gameObject;
        if (markText == null)
        {
            markText = (GameObject)Instantiate(markTextPrefab);
            markText.name = name;
        }
        markText.transform.SetParent(this.transform);
        var x = this.gameObject.GetComponent<RectTransform>().rect.width / 2 - MarkTextWidth / 2;
        var rectTransform = markText.GetComponent<RectTransform>();
        rectTransform.sizeDelta = new Vector2(MarkTextWidth, MarkTextHeight);
        rectTransform.anchoredPosition = new Vector2(-x, yPos);
        var text = markText.GetComponent<Text>();
        text.text = msg;
        text.color = MarkTextColor;
        text.enabled = true;
    }

    IEnumerator CreateMarkTextUnit(float yPos, string msg)
    {
        yield return new WaitForSeconds(0);
        CreateOneMarkText(yPos, msg);
    }

    IEnumerator CreateMarkText(float markTextYPos, float markText)
    {
        yield return new WaitForSeconds(0);
        CreateOneMarkText(markTextYPos, markText.ToString() + "-");
    }

    IEnumerator DisableAllMarkTextWithoutUnit()
    {
        yield return new WaitForSeconds(0);
        var children = this.GetComponentsInChildren<Text>();
        foreach (var child in children)
        {
            if (child.name != MarkTextNameBase + unit)
                child.enabled = false;
        }
    }

    IEnumerator DestoryAllDisabledMarkText()
    {
        yield return new WaitForSeconds(0);
        var children = this.GetComponentsInChildren<Text>();
        foreach (var child in children)
        {
            if (!child.enabled)
                DestroyImmediate(child.gameObject);
        }
    }

    private float CalcRealStartMarkText(float markText)
    {
        int basePrecision = 1;
        while (markText < basePrecision || markText > basePrecision * 10)
        {
            if (markText < basePrecision)
                basePrecision /= 10;
            else if (markText > basePrecision * 10)
                basePrecision *= 10;
            else
                break;
        }
        basePrecision /= 10;

        return Mathf.CeilToInt(markText / basePrecision) * basePrecision;
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        var rect = this.GetPixelAdjustedRect();
        vh.Clear();
        //ColorBar矩形的坐标位置(像素单位)
        float yMax, yMin, xMin, xMax;
        yMax = rect.yMax - MarkTextHeight / 2;
        //是因为底部需要预留单位信息,所以多加了一个空间。
        yMin = rect.yMin + MarkTextHeight / 2 + MarkTextHeight / 2;
        xMin = rect.xMin + MarkTextWidth;
        xMax = rect.xMax;

        var markTextNum = CalcMarkTextNum(MarkTextHeight, yMax - yMin);
        float markTextStep = CalcMarkTextStep(MarkTabs, markTextNum, markTextMax - markTextMin);
        var rate = (yMax - yMin) / (markTextMax - markTextMin);
        var realMarkTextMin = CalcRealStartMarkText(markTextMin);

        //添加单位
        StartCoroutine(CreateMarkTextUnit(yMin - MarkTextHeight / 2, unit));
        StartCoroutine(DisableAllMarkTextWithoutUnit());

        var markText = realMarkTextMin;
        while (markText <= markTextMax)
        {
            //当前刻度线
            var markTextYPos = (markText - markTextMin) * rate + yMin;
            StartCoroutine(CreateMarkText(markTextYPos, markText));

            //由于两个刻度线之间的跨度较大,只画一个矩形颜色过渡不太好,所以这里在两个刻度线之间画多个
            var uiVertexQuadStep = markTextStep / UIVertexQuadNumBetweenTwoMarkText;
            for (int i = 0; i < UIVertexQuadNumBetweenTwoMarkText; i++)
            {
                //前一个刻度线
                var markTextPre = markText - (i + 1) * uiVertexQuadStep;
                if (markTextPre < markTextMin)
                    markTextPre = markTextMin;

                var markTextYPosPre = (markTextPre - markTextMin) * rate + yMin;

                var verts = CreateUIVertexQuad(xMin, xMax, markTextYPosPre, markTextYPos, markTextPre, markText);
                vh.AddUIVertexQuad(verts);

                if (markTextPre < markTextMin)
                    break;
            }
            //下一个刻度线
            markText += markTextStep;
        }

        //跳到这里说明刻度线已经大于最大值了,超出最大刻度线的肯定不需要画出来
        //最大刻度线也不需要画出来,应该它可能不是我们想要的一个数据精度
        //但是最大刻度线对应的颜色值需要我们画出来的,就相当于最小刻度颜色值也需要画出来
        var lastmarkText = markText - markTextStep;//这是画的最大的一条刻度线
        var lastmarkTextYPos = (lastmarkText - markTextMin) * rate + yMin;

        var lastverts = CreateUIVertexQuad(xMin, xMax, lastmarkTextYPos, yMax, lastmarkText, markTextMax);
        vh.AddUIVertexQuad(lastverts);

        StartCoroutine(DestoryAllDisabledMarkText());
    }

    private UIVertex[] CreateUIVertexQuad(float xMin, float xMax,
        float yBottomPos, float yTopPos, float markBottom, float markTop)
    {
        UIVertex[] verts = new UIVertex[4];
        verts[0] = CreateOneUIVertex(new Vector2(xMin, yBottomPos), markBottom);
        verts[1] = CreateOneUIVertex(new Vector2(xMax, yBottomPos), markBottom);

        verts[2] = CreateOneUIVertex(new Vector2(xMax, yTopPos), markTop);
        verts[3] = CreateOneUIVertex(new Vector2(xMin, yTopPos), markTop);

        return verts;
    }

    private UIVertex CreateOneUIVertex(Vector2 pos, float h)
    {
        UIVertex vert = new UIVertex();
        vert.position = new Vector3(pos.x, pos.y);
        if (CalcOneColor != null)
            vert.color = CalcOneColor.Invoke(h, markTextMin, markTextMax);
        vert.uv0 = Vector2.zero;

        return vert;
    }

    /// <summary>
    /// 计算刻度线的个数,乘以3是因为给予刻度线之间的间隔
    /// </summary>
    /// <param name="markTextHeigh">一个刻度线占的高度</param>
    /// <param name="colorBarHeigh">整个轴的长度</param>
    /// <returns></returns>
    private int CalcMarkTextNum(float markTextHeigh, float colorBarHeigh)
    {
        return Mathf.FloorToInt(colorBarHeigh / (markTextHeigh * 3));
    }

    /// <summary>
    /// 寻找最佳的一个刻度步长
    /// </summary>
    /// <param name="markTab">提供备选的步长基数</param>
    /// <param name="markNum">刻度个数</param>
    /// <param name="MarkTextRange">需要跨越的整个范围</param>
    /// <returns>最佳步长</returns>
    private float CalcMarkTextStep(float[] markTab, int markNum, float MarkTextRange)
    {
        float step = MarkTextRange / (markNum > 0 ? markNum : 1);
        float markScale = 1;
        float mark = markTab[0];
        while (step < mark * markScale || step > mark * markScale * 10)
        {
            if (step < mark * markScale)
                markScale /= 10;
            else if (step > mark * markScale * 10)
                markScale *= 10;
            else
                break;
        }

        step /= markScale;
        for (int i = 1; i < markTab.Length; i++)
        {
            if (Mathf.Abs(markTab[i] - step) < Mathf.Abs(mark - step))
                mark = markTab[i];
        }

        return mark * markScale;
    }
}

考虑到想做成控件,所以我们将可变的东西写在了另外一个用户脚本中:

public class CustomColorBar : MonoBehaviour
{
    public ColorBar Bar;
    public float Max
    {
        get { return Bar.MarkTextMax; }
        set { Bar.MarkTextMax = value; }
    }

    public float Min
    {
        get { return Bar.MarkTextMin; }
        set { Bar.MarkTextMin = value; }
    }

    // Use this for initialization
    void Start()
    {
        Bar.CalcOneColor = CreateOneColor;
        StartCoroutine(UpdateMaxAndMin());
    }

    IEnumerator UpdateMaxAndMin()
    {
        while (true)
        {
            Min= Random.Range(0, 3000);
            yield return new WaitForSeconds(5);
            Max = Random.Range(Min, 7000);
            yield return new WaitForSeconds(5);
        }
    }

    // Update is called once per frame
    void Update()
    {

    }

    private Color CreateOneColor(float value, float min, float max)
    {
        float hMin = 0, hMax = 0.80f;

        var h = (hMax - hMin) / (max - min) * (value - min) + hMin;

        return Color.HSVToRGB(h, 1, 1);
    }
}

在这里插入图片描述

四、自定义控件

在这里插入图片描述

然后在Editor文件夹中增加了一个脚本:

public class ColorBarMenu : MonoBehaviour
{
    ///如果要让Hierarchy里面的Gameobject通过鼠标右键单击
    ///弹出对话框中出现该选项,则需要将该选项加入到"GameObject"目录下
    [MenuItem("GameObject/UI/ColorBar")]
    public static void AddColorBarInGameObject()
    {

        GameObject parent = null;
        if (null != Selection.activeTransform)
        {
            parent = Selection.activeTransform.gameObject;
        }
        else
        {
            parent = null;
        }

        if ((null == parent) || (null == parent.GetComponentInParent<Canvas>()))
        {
            Canvas canvas = FindObjectOfType<Canvas>();
            if (null == canvas)
            {
                Debug.LogError("AddColorBar : can not find a canvas in scene!");
                return;
            }
            else
            {
                parent = FindObjectOfType<Canvas>().gameObject;
            }
        }

        GameObject prefab = Resources.Load("Prefabs/ColorBar") as GameObject;
        if (null == prefab)
        {
            Debug.LogError("AddColorBar : Load ColorBar Error!");
            return;
        }

        GameObject colorBar;
        if (null != parent)
            colorBar = Instantiate(prefab, parent.transform);
        else
            colorBar = Instantiate(prefab);

        if (null == colorBar)
        {
            Debug.LogError("AddColorBar : Instantiate ColorBar Error!");
            return;
        }

        Undo.RegisterCreatedObjectUndo(colorBar, "Created ColorBar");
        colorBar.name = "ColorBar";
    }
}

这个脚本就是为了右键可以直接添加该控件。所有源码在:heater404/ColorBar (github.com)
源码中有两个示例:

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值