共计 3086 个字符,预计需要花费 8 分钟才能阅读完成。
【博物纳新】是 UWA 旨在为开发者推荐新颖、易用、有趣的开源项目,帮助大家在项目研发之余发现世界上的热门项目、前沿技术或者令人惊叹的视觉效果,并探索将其应用到自己项目的可行性。很多时候,我们并不知道自己想要什么,直到某一天我们遇到了它。
更多精彩内容请关注:lab.uwa4d.com
导读
图表(Chart)是我们最为广泛使用的数据可视化工具。
对于简单的图表,Office 系软件就完全可以胜任了。如果需要更加美观和专业,也可以用 ECharts、Highcharts、D3、G2 之类专门的工具。在各类编程语言中,也有各种图形库用来制作图表。
那么今天,我们来介绍一个可以在 Unity 的 UI 中绘制图表的开源库项目——XCharts。它参考了 ECharts 的风格,通过 UGUI 绘制,可以静态或使用代码动态地控制内容。
开源库链接:https://lab.uwa4d.com/lab/5bc42d5404617c5805d4d685
特性
1、内置丰富示例,参数可视化配置,效果实时预览,纯源码绘制;
2、支持折线图(LineChart)、柱状图(BarChart)、饼图(PieChart)、雷达图(RadarChart);
3、支持 Default、Light、Dark 三种默认主题切换,自定义主题;
4、支持多数据密集图表;
5、折线图通过参数可配置出:折线图、曲线图、面积图等;
6、饼图通过参数可配置出:饼图、环形图、南丁格尔玫瑰图等。
目前项目仍在不断更新之中。
使用方法
在开源库下载好 XCharts 后,我们可以直接作为 Unity 项目打开,也可以将其导入到现有的项目,然后我们只需要把对应的图表脚本添加到一个 Canvas 的子对象中。
这样基本的配置就完成了。更加详细的控制图表内容以及代码使用的方法,可以在项目自带的演示场景中找到。
那么既然可以在 UI 里动态绘制图表,我们就来尝试做一些有意义的事情吧。(以下均使用 LowPoly Environment Pack 的Demo1场景测试)
1、通过折线图显示帧数走势
帧数计算有多种方法,最简单的是可以取完成最后一帧的时间的倒数:
fps=1/Time.deltaTime;
但这实际上是用一帧的时间来估计一秒经过的帧数,而且全部显示出来会有刷新过快的情况;另一种更常用的方法是统计一下 1s 左右走过的帧数,如下:
ftime += Time.deltaTime;
frameCount++;
if (ftime >= 1f)
{
fps = frameCount / ftime;
// 这里添加图表数据控制代码
ftime = 0f;
frameCount = 0f;
}
需要添加的图表代码:
chart.AddXAxisData(Time.frameCount.ToString()); // 添加横轴数据,这里我们使用总帧数
chart.AddData(0, fps);// 添加对应数据
chart.RefreshChart();// 刷新图表
然后我们在 Inspector 中把折线图脚本中的 Max Cache Data Number 设置为我们希望图表能够同时显示的最大数据量,超过这个值图表就会进行推移。这样简单的帧率折线图就完成了。
我们可以尝试隐藏除线条以外的元素,这在 Inspector 中可以很容易的控制,十分简洁的帧率走势就呈现了出来,如下图:
2、通过折线图显示 Mono 内存
Mono 内存分为两个部分:已用内存 (Used) 和堆内存(Heap),因为它们特殊的关系,我们可以将他们显示在同一个折线图中。要得到这两个数据,我们可以用使用下面的两段代码:
Profiler.GetMonoHeapSizeLong()
Profiler.GetMonoUsedSizeLong()
与查看 fps 相同,我们将其放入 Update()里,并隔 1s 左右刷新:
ftime += Time.deltaTime;
if(ftime>=1f)
{
ftime = 0f;
chart.AddXAxisData(Time.frameCount.ToString());
chart.AddData("Heap", Profiler.GetMonoHeapSizeLong()/ 1048576f);// 堆内存 MB
chart.AddData("Used", Profiler.GetMonoUsedSizeLong()/ 1048576f);// 占用内存 MB
chart.RefreshChart();// 刷新图表}
简单地样式调整之后,得到了下面的效果图,两条折线可以很清晰地反映出 Mono 内存的变化。
3、通过饼图显示材质占比
统计贴图个数占比或者贴图内存占比会更加具有意义,但在非 Editor 环境下得到所有可见贴图并不方便,为了简单起见,这里选择材质个数进行举例。
以下是部分主要代码,通过渲染器查找到所有可见的材质,使用字典 matNames 辅助统计:
matNames.Clear();
Renderer[] renderers = (Renderer[])FindObjectsOfType(typeof(Renderer));
foreach (Renderer renderer in renderers) {if (renderer.isVisible){foreach (Material material in renderer.sharedMaterials){if (matNames.ContainsKey(material.name)) {int temp = ++matNames[material.name];
chart.UpdateData(material.name, temp); // 图表会自动计算比例,这里只统计个数
}
else {matNames.Add(material.name, 1);
chart.AddData(material.name, 1);
}}}}
复杂的遍历工作计算开销比较大,我们这里添加协程来延时 3s 运行。值得注意的是,对于元素减少,即材质不在视野里的情况,相应的数据列表应该被裁剪,但源码中并没有实现这种功能的方法;我们可以利用该项目纯源码绘制的优点,自己在 series.cs 里添加新的方法:
public void RemoveSerie() => m_Series = new List<Serie>();
这样每次遍历之前添加 chart.series.RemoveSerie()清空数据列表,达到调整列表大小的作用。
以下是运行效果图:
简单的主题修改:
这样,显示材质占比的饼图也有模有样了。
打包测试
最后,我们尝试打包一下,并测试其运行效果:
平台信息:Android 8.1,meizu 16th
编者这里打包遇到了一些问题,检查发现图表源代码有一部分被限定在了 Editor 环境之中。
不过我们只要见招拆招,删除这段代码及其所有的引用即可,并不影响打包后的正常使用。
下面就是真机的运行效果:
折线图(FPS)和 饼图(材质占比)
折线图(FPS)和 折线图(Mono 内存)
我们想要的图表这样就基本完成了。
结语
以上就是本次开源库介绍的全部内容了,我们通过 3 个例子演示了使用 XCharts 在 UI 中绘制动态图表的方法;
不管是运行帧率、Mono 内存还是材质占比,将数据的动态趋势显示出来都具有非常直观的参考意义。
无论如何,动态图表是数据可视化的有效手段,希望这篇文章能对有需要的读者有所帮助。
快用 UWA Lab 合辑 Mark 好项目!
今天的推荐就到这儿啦,或者它可直接使用,或者它需要您的润色,或者它启发了您的思路 ……
请不要吝啬您的点赞和转发,让我们知道我们在做对的事。当然如果您可以留言给出宝贵的意见,我们会越做越好。