XCharts开源库介绍

46次阅读

共计 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 PackDemo1场景测试)

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 好项目!

今天的推荐就到这儿啦,或者它可直接使用,或者它需要您的润色,或者它启发了您的思路 ……

请不要吝啬您的点赞和转发,让我们知道我们在做对的事。当然如果您可以留言给出宝贵的意见,我们会越做越好。

正文完
 0