Unity 做一个消耗大了一些但是效果好了一些的Circle Outline

你是否有过这样的经历?当你在Inspector的AddComponent了一个Outline时,它的Alpha值永远需要手动调整一下。
你是否有过这样的经历?当你在一个字号比较大的Text挂上Outline时,它并不是所有的地方都有描边。

来来来,今天就解决这两个问题。

首先第一个,当你Add了一个Outline时。
在这里插入图片描述
Color.a一定要只有一半,就一定要手动拉到满。(别问我为什么一定要拉到满,问美术。)
反正,我是烦得很。

so……
在这里插入图片描述

using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

[InitializeOnLoad]
public class ObjectFactoryManager
{
    
    
    static ObjectFactoryManager()
    {
    
    
        ObjectFactory.componentWasAdded += ComponentWasAdded;
    }

    private static void ComponentWasAdded(Component comp)
    {
    
    
        if (comp.GetType() == typeof(Image))
        {
    
    
            Image image = (Image)comp;
            image.raycastTarget = false;
        }
        else if (comp.GetType() == typeof(Outline) || comp.GetType() == typeof(CircleOutline))
        {
    
    
            Outline outline = (Outline)comp;
            Color effectColor = outline.effectColor;
            effectColor.a = 1f;
            outline.effectColor = effectColor;
        }
    }
}

我来解释一下,这几行都在干什么。
1.[InitializeOnLoad]
在这里插入图片描述
“当Unity加载或者当你的脚本加载完成时,就会实例化所有声明了这个属性的类”。
2.ObjectFactory.componentWasAdded += ComponentWasAdded;
就是一个事件,还用多说嘛~
3.ComponentWasAdded(Component comp)
很直白,就是判断一下类型,然后修改对应的组件。(不要问我为什么不用Switch,要是能用的话,我早就用惹!)

接下来就是另一个问题了。
先来张最常见的例子:
在这里插入图片描述
看着这糟心的白色的边边角角,难受的一批。
开始百度一下各路大神都是怎么做的。大体上都是说用shader做。但是吧,一来我看不懂,二来不知道为什么就不生效……
直到我看到了一篇文章,说挂两个outline就好了。
厉害呀,在我对Unity的了解里,用一个Outline就会多产生4倍的顶点,因为他就是复制了4分,然后向着上下左右移一移就完事了。这加上两层,直接5倍乘5倍的顶点就出来了。
这大概是我见过的最离谱的解决办法了……

就在这时候,我突然想起了我的老东家的做法,向着八个方向做8个!
好像可行,虽然会再多四倍的顶点数,但是效果还是不错的。

so……
在这里插入图片描述

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CircleOutline : Outline
{
    
    
    //斜向圆形折扣比例
    private readonly float diagonalRotia = 0.707f;

    public override void ModifyMesh(VertexHelper vh)
    {
    
    
        if (!IsActive())
            return;

        List<UIVertex> verts = new List<UIVertex>();
        vh.GetUIVertexStream(verts);

        //改变偏移数据生成8倍的顶点数据
        int start = 0;
        int end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, effectDistance.x * diagonalRotia, effectDistance.y * diagonalRotia);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, effectDistance.x, 0);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, effectDistance.x * diagonalRotia, -effectDistance.y * diagonalRotia);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, 0, -effectDistance.y);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, -effectDistance.x * diagonalRotia, -effectDistance.y * diagonalRotia);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, -effectDistance.x, 0);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, -effectDistance.x * diagonalRotia, effectDistance.y * diagonalRotia);

        start = end;
        end = verts.Count;
        ApplyShadow(verts, effectColor, start, verts.Count, 0, effectDistance.y);

        //重添加到原始数据中
        vh.Clear();
        vh.AddUIVertexTriangleStream(verts);

        //清理
        verts.Clear();
        verts = null;
    }
}

别觉得我写的很墨迹,Unity的UI源码就是做了四次复制Shadow……
简单说一下,0.707f的比例,是因为要做圆形而算出来的。
其他的,别问,没啥看不明白的,你看不明白的点……就再问我就好了,这一块的源码我也没有细看过。

最后看一下实际效果
在这里插入图片描述
嗯,舒服多了。

在这里插入图片描述
补充:
问了一下公司大佬,用Shader和Outline的区别是,shader的消耗在采样上,outline是复制三角片的顶点。shader采样8次就能达到我这个outline的效果,省了不少。
然而我就是不会shader,唉

猜你喜欢

转载自blog.csdn.net/qql7267/article/details/109602513