UE接入ECharts,让数据会说话
UE 接入 ECharts,让数据会说话
先说结论:UE 里不需要自己画图表。把 ECharts 跑在 Web 面板里,通过消息通道跟 UE 三维场景双向联动,前端写图表,UE 做渲染,两边对接消息契约就行。
很多 UE 项目里,数据图表是刚需——设备监控面板、实时统计大屏、AI 分析结果展示——但用 UMG 画图表是一件极其痛苦的事。一个折线图,你要自己处理坐标轴缩放、数据映射、悬停提示、动画过渡,做出来的效果还比不上前端同学五分钟写出来的 ECharts demo。
这不是你的问题。ECharts 背后是百度整个前端团队十年的积累,它有 50+ 种图表类型、内置交互和动画、百万级数据渲染优化。你用 UMG 从零造轮子,就是在跟一个成熟生态打肉搏战。
ECharts 到底强在哪
给没接触过的 UE 开发者简单介绍一下:
- 50+ 图表类型:折线图、柱状图、饼图、散点图、热力图、地图、3D 地球、仪表盘、桑基图、关系图……覆盖几乎所有数据可视化场景
- 开箱即用的交互:缩放、拖拽、图例切换、数据点选中、tooltip 悬停,一行代码不用写
- 百万级数据量:支持增量渲染和 WebGL 加速,大屏场景不卡顿
- 高度可定制:颜色、字体、动画、主题、坐标轴,全都可以配
- 生态丰富:Vue/React 封装、地图插件、时序数据插件、AI 辅助生成配置
所以问题不是"要不要用 ECharts",而是"怎么在 UE 里跑 ECharts"。
方案:把 ECharts 跑在 Web 面板里
架构很简单:
ECharts HTML 页面
↓
WebNativeBrowser(CEF GPU 渲染)
↓
UE 场景中的 Web 面板
↓
JS ↔ UE 消息通道(< 1ms 延迟)
↓
UE 蓝图 / C++ 业务逻辑
和原生 UE 控件不同,Web 面板里的 ECharts 是通过 GPU 共享纹理直接渲染到 UE 视口的,不经过 CPU 拷贝,不影响引擎渲染性能。
第一步:创建一个 ECharts 页面
你只需要写一个普通的 HTML 文件,放在插件的 Content 目录下:
<!-- Content/webnative/html/charts/monitor.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: rgba(0,0,0,0); overflow: hidden; }
#chart { width: 100vw; height: 100vh; }
</style>
</head>
<body>
<div id="chart"></div>
<script>
const chart = echarts.init(document.getElementById('chart'), 'dark');
// 从 UE 接收数据并更新图表
WebNative.on('Chart.Data.Update', (messageBody) => {
const data = JSON.parse(messageBody);
chart.setOption({
title: { text: data.title, textStyle: { color: '#fff' } },
tooltip: { trigger: 'axis' },
legend: { data: data.legends, textStyle: { color: '#aaa' } },
xAxis: { type: 'category', data: data.xAxis },
yAxis: { type: 'value' },
series: data.series
});
});
// 图表点击 → 通知 UE
chart.on('click', (params) => {
WebNative.send('Chart.Point.Click', JSON.stringify({
seriesName: params.seriesName,
dataIndex: params.dataIndex,
value: params.value,
name: params.name
}));
});
// 图表缩放 → 通知 UE
chart.on('datazoom', (params) => {
WebNative.send('Chart.Zoom.Change', JSON.stringify({
start: params.start,
end: params.end
}));
});
// 通知 UE 图表已就绪
WebNative.send('Chart.Ready', '{}');
</script>
</body>
</html>
第二步:UE 端发送数据到图表
在 UE 蓝图或 C++ 中,调用 SendMessageToJS 推送数据:
// UE C++ 端:构造 ECharts 数据并发送
void AMyDataActor::UpdateChart()
{
TSharedPtr<FJsonObject> Root = MakeShareable(new FJsonObject);
Root->SetStringField("title", "设备实时温度监控");
// xAxis:时间点
TArray<TSharedPtr<FJsonValue>> XAxisArray;
XAxisArray.Add(MakeShareable(new FJsonValueString("08:00")));
XAxisArray.Add(MakeShareable(new FJsonValueString("09:00")));
XAxisArray.Add(MakeShareable(new FJsonValueString("10:00")));
XAxisArray.Add(MakeShareable(new FJsonValueString("11:00")));
Root->SetArrayField("xAxis", XAxisArray);
// legends:图例
TArray<TSharedPtr<FJsonValue>> LegendsArray;
LegendsArray.Add(MakeShareable(new FJsonValueString("注塑机A")));
LegendsArray.Add(MakeShareable(new FJsonValueString("注塑机B")));
Root->SetArrayField("legends", LegendsArray);
// series:数据系列(ECharts 标准格式)
TArray<TSharedPtr<FJsonValue>> SeriesArray;
TSharedPtr<FJsonObject> SeriesA = MakeShareable(new FJsonObject);
SeriesA->SetStringField("name", "注塑机A");
SeriesA->SetStringField("type", "line");
TArray<TSharedPtr<FJsonValue>> DataA;
DataA.Add(MakeShareable(new FJsonValueNumber(120)));
DataA.Add(MakeShareable(new FJsonValueNumber(132)));
DataA.Add(MakeShareable(new FJsonValueNumber(101)));
DataA.Add(MakeShareable(new FJsonValueNumber(134)));
SeriesA->SetArrayField("data", DataA);
SeriesArray.Add(MakeShareable(new FJsonValueObject(SeriesA)));
TSharedPtr<FJsonObject> SeriesB = MakeShareable(new FJsonObject);
SeriesB->SetStringField("name", "注塑机B");
SeriesB->SetStringField("type", "line");
TArray<TSharedPtr<FJsonValue>> DataB;
DataB.Add(MakeShareable(new FJsonValueNumber(220)));
DataB.Add(MakeShareable(new FJsonValueNumber(182)));
DataB.Add(MakeShareable(new FJsonValueNumber(191)));
DataB.Add(MakeShareable(new FJsonValueNumber(234)));
SeriesB->SetArrayField("data", DataB);
SeriesArray.Add(MakeShareable(new FJsonValueObject(SeriesB)));
Root->SetArrayField("series", SeriesArray);
FString JsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
FJsonSerializer::Serialize(Root.ToSharedRef(), Writer);
SendMessageToJS("Chart.Data.Update", JsonString);
}
第三步:图表交互反馈到三维场景
当用户点击图表上的数据点时,三维场景可以做出响应:
void AMyDataActor::OnMessageReceived(const FString& FunctionName, const FString& MessageBody)
{
if (FunctionName == "Chart.Point.Click")
{
TSharedPtr<FJsonObject> Json;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(MessageBody);
if (FJsonSerializer::Deserialize(Reader, Json))
{
FString SeriesName = Json->GetStringField("seriesName");
int32 DataIndex = Json->GetIntegerField("dataIndex");
// 三维场景聚焦对应设备
AActor* Device = FindDeviceByName(SeriesName);
if (Device)
{
FocusCameraOn(Device);
HighlightActor(Device);
}
}
}
}
进阶:复杂图表场景
实时数据流
如果你需要每秒多次推送数据(比如设备振动曲线),建议做批量处理:
// 前端:合并高频数据,按动画帧更新
let pendingData = [];
let scheduled = false;
WebNative.on('Chart.RealTime.Data', (messageBody) => {
pendingData.push(JSON.parse(messageBody));
if (!scheduled) {
scheduled = true;
requestAnimationFrame(() => {
const last = pendingData[pendingData.length - 1];
chart.setOption({
series: [{
data: chart.getOption().series[0].data.concat(pendingData.map(d => d.value)).slice(-100)
}]
});
pendingData = [];
scheduled = false;
});
}
});
3D 图表与场景联动
ECharts 支持 WebGL 3D 渲染,可以做 3D 地球、3D 散点图、3D 曲面。配合 UE 的场景相机:
// 当 UE 相机移动时,同步更新 3D 图表的视角
WebNative.on('Scene.Camera.Move', (messageBody) => {
const camera = JSON.parse(messageBody);
// ECharts GL 图表联动
my3DChart.setOption({
globe: {
viewControl: {
alpha: camera.pitch,
beta: camera.yaw
}
}
});
});
地图 + 三维场景
ECharts 内置中国地图和世界地图(需注册),可以作为 UE 三维场景的鸟瞰概览:
用户在地图上点击上海园区 → UE 三维场景飞到上海 → 显示园区细节
用户在 UE 里切换到全局视角 → 地图自动缩放到对应区域
性能:消息通道是关键
ECharts 和 UE 之间的联动性能,取决于中间的消息通道。WebNativeBrowser 的消息通道:
| 指标 | 数据 |
|---|---|
| 单条消息延迟 | < 1ms |
| 10 万条消息 | ~220ms |
| 每秒最大吞吐 | 45 万条/秒 |
| 每帧最大派发 | 10 万条 |
对于图表联动场景来说,这个性能绰绰有余。即使每秒 60 帧刷数据,每帧 800 条消息,延迟仍然在毫秒级。
对比:你用 UMG 画图表要多久
用 UMG 实现一个带 tooltip、缩放、图例切换的折线图:
- 用 UCanvas 自己画坐标轴——半天
- 处理数据到像素的映射——半天
- 实现鼠标悬停 tooltip——半天
- 实现拖拽缩放和滚轮缩放——一天
- 调试边界情况、性能优化——一天
- 换个项目想复用——发现耦合太死,重写
用 ECharts + WebNativeBrowser:
- 写一个 50 行 HTML 配置——十分钟
- 换项目:复制 HTML 文件,改配置——五分钟
- 效果:吊打手写版
把时间花在三维场景和业务逻辑上,图表的事交给 ECharts。
总结
UE 里做数据可视化,最优路径不是自己画——是把成熟的 Web 生态引进来。ECharts 经过了百万开发者和万亿次渲染的验证,UE 的三维渲染能力和 WebNativeBrowser 的 GPU 直通渲染让它能完美嵌入 UE 视口。
- 前端写图表配置 → 十分钟一个复杂图表
- UE 推送数据 → 一行
SendMessageToJS - 图表交互回传 → 三维场景响应
- 同一套页面 → Windows / Linux 通用
让 UE 做它最擅长的事,让 Web 做它最擅长的事。
如果这篇对你有帮助,欢迎点赞收藏。关于 WebNativeBrowser 的完整文档和示例,可以访问我们的 GitHub 仓库:starTechnology1994/UEWebNativeBrowser
商务合作 / 授权咨询:startechnology1994@163.com
浙公网安备 33010602011771号