你是否有过这样的经历?当你在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,唉