UGUI能量图
游戏中为了展现角色属性,突出职业特点,经常用到“六芒星”,玩家可以根据六芒星的形状,更好的分析当前角色的属性和特点,如图:
最近正在研究UGUI,为了理解UGUI组织顶点渲染的机制,就用UGUI实现了一套“六芒星”。
在Canvas节点下,所有显示的UI控件都有一个CanvasRenderer组件,这个组件就是用来组织UI控件顶点的。CanvasRenderer有设置Mesh的接口,通过角色的属性,构建出六芒星mesh,并传递给CanvasRenderer,使其符合UGUI渲染机制(深度,Order等)统一渲染。
Unity提供渲染网格接口类就是Mesh,通过Mesh我们可以设置顶点属性(位置,uv,颜色等),以及Mesh的顶点索引数组,就可以构建一个完整的Mesh对象了。为了使其在Canvas中正常显示,我们实例化一个Shader作为Material对象,赋值到CanvasRenderer组件对象中,即可完成渲染。
我们以六芒星为例,六芒星将平面360度平均划分为6份,每份60度,即可确定每个属性的方向,再根据属性的值(相当于向量的模),就可以得到对应的“属性向量”,将6个属性向量的终点连在一起,就可以渲染出整体的六芒星。
为了便于扩展六芒星为“五芒星”,“七芒星”等,我们允许设置以下几个属性:
startDirection:第一个属性的方向,通过这个方向值以及每个属性之间的角度,可以得到其他属性的方向。
attributes:属性数组,数组的长度表示了“N芒星”。
fullStrength:满属性值,通过属性值/满属性值,可以得到这个属性的比例,用于构建六芒星UI控件。
1
2
3
4
5
6
|
// 起始方向
public
Vector3 startDirection =
new
Vector3(0, 1, 0);
// 星属性
public
int
[] attributes =
null
;
// 最大值
public
float
fullStrength = 100f;
|
通过将360度平均划分为N份,以及向量旋转公式,可以得到每个属性的方向向量,算法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 获取每个属性点的方向向量
int
starsCount =
this
.attributes.Length;
List<Vector3> directionList =
new
List<Vector3>(starsCount);
float
deltaAngle =
this
.circle / starsCount;
for
(
int
i = 0; i < attributes.Length; ++i)
{
float
angle = i * deltaAngle;
float
rad = Mathf.Deg2Rad * angle;
float
sinA = Mathf.Sin(rad);
float
cosA = Mathf.Cos(rad);
directionList.Add(
new
Vector3(startDirection.x * cosA + startDirection.y * sinA,
-startDirection.x * sinA + startDirection.y * cosA, 0));
}
|
接下来计算六芒星中各顶点的位置,要构建六芒星,除了每个属性的顶点外,还需要一个中心点。属性点根据每个属性的方向(单位向量)*属性值可得,算法如下:
1
2
3
4
5
6
7
8
9
10
11
|
Mesh mesh =
new
Mesh();
// 设置顶点位置属性
int
verticesCount = starsCount + 1;
List<Vector3> vertices =
new
List<Vector3>(verticesCount);
vertices.Add(Vector3.zero);
for
(
int
i = 1; i < verticesCount; ++i)
{
int
index = i - 1;
vertices.Add(directionList[index] *
this
.attributes[index] /
this
.fullStrength * rectTransform.sizeDelta.x);
}
mesh.SetVertices(vertices);
|
为了表现更丰富一点,我们为每个属性设置一个颜色,属性的颜色值根据属性强度变深,算法如下:
1
2
3
4
5
6
7
8
9
10
11
|
// 设置颜色属性
List<Color32> colors =
new
List<Color32>();
colors.Add(
new
Color32(255, 255, 255, 255));
for
(
int
i = 0; i < starsCount; ++i)
{
float
strength = attributes[i] / rectTransform.sizeDelta.x;
byte
r = (
byte
)(strength * 200);
Color32 c =
new
Color32(r, 0, 0, 255);
colors.Add(c);
}
mesh.SetColors(colors);
|
Mesh对象的顶点属性设置完成后,还要为顶点设置索引数组,六芒星网格是由6个三角形构建而成,这6个三角形有一个共点(中心点),通过中心点及任意两个相邻的属性顶点组成6个三角形,算法如下:
1
2
3
4
5
6
7
8
9
10
11
|
// 设置索引属性
int
[] indices =
new
int
[3 * starsCount];
for
(
int
i = 0; i < starsCount; ++i)
{
int
index = 3 * i;
indices[index] = 0;
indices[index + 1] = i + 1;
indices[index + 2] = (i + 2) > starsCount ? (i + 2 - starsCount) : (i + 2);
}
mesh.SetIndices(indices, MeshTopology.Triangles, 0);
canvasRenderer.SetMesh(mesh);
|
最后设置材质
1
2
|
Material material =
new
Material(Shader.Find(
"UI/Default"
));
canvasRenderer.SetMaterial(material,
null
);
|
效果如下图