ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Unity WebGL集成海康监控流与实时数据可视化实战

Unity WebGL集成海康监控流与实时数据可视化实战 1. 项目概述当Unity WebGL遇上海康监控流最近在做一个工业数字孪生的项目客户要求在Web端的三维场景里实时查看部署在现场的海康威视监控画面。这个需求听起来简单不就是播个视频流嘛但真做起来坑是一个接一个。核心挑战在于海康的监控流通常是RTSP或私有协议而Unity的WebGL平台运行在浏览器沙箱里无法直接访问本地网络设备或使用传统的桌面端视频插件。最终我们确定的方案是Unity WebGL AVPro Video 海康M3U8转码流 XCharts图表叠加。这套组合拳打下来不仅实现了视频流的稳定播放还能在视频画面上叠加实时数据图表完美契合了监控与数据可视化结合的需求。简单来说这个项目就是要在浏览器里通过一个Unity构建的3D Web应用无插件播放海康摄像头的实时视频并且能在视频上“画”出一些温度、压力等数据的曲线或柱状图。它适合那些需要在Web端集成专业安防监控与三维可视化能力的开发者比如智慧园区、智慧工厂、远程巡检等场景。如果你正在为如何把RTSP流搬上WebGL而头疼或者想在视频流上做增强现实式的数据标注那接下来的内容应该能给你不少参考。2. 技术栈选型与架构思路拆解为什么是这几样技术每一环的选择背后都有具体的考量并非随意堆砌。2.1 为什么是Unity WebGL首先项目主体是一个三维可视化场景可能包含复杂的设备模型、动画和交互。Unity在3D渲染和跨平台发布方面的成熟度是首选原因。WebGL作为其发布平台之一允许我们将内容直接运行在浏览器中用户无需安装任何客户端或插件访问链接即可极大地降低了部署和使用的门槛。但WebGL的限制也很明显它是一个受沙箱保护的、功能受限的JavaScript执行环境无法直接调用系统API如DirectShow、FFmpeg库网络请求也需遵循浏览器的CORS策略。2.2 视频播放方案为什么是AVPro VideoUnity内置的VideoPlayer组件在桌面端尚可一用但在WebGL平台功能孱弱格式支持有限性能也不佳。我们需要一个专业的、为WebGL深度优化的视频播放解决方案。AVPro Video是Unity Asset Store上最强大的视频播放插件之一其核心优势在于针对不同平台包括WebGL提供了底层渲染优化和广泛的格式支持。对于WebGLAVPro Video通过其内部机制能够高效地处理来自网络或内存的视频数据并渲染到Unity的纹理上这对于我们将视频作为材质贴到3D物体表面或UI上至关重要。更重要的是AVPro Video支持以MediaPlayer对象为核心动态加载和播放视频源。我们可以通过代码将海康摄像头转换后得到的M3U8链接赋值给MediaPlayer的Path属性从而实现流的加载与控制播放、暂停、跳转。2.3 流媒体协议为什么是M3U8海康摄像头的原始流多是RTSP如rtsp://admin:password192.168.1.64:554/Streaming/Channels/101。但RTSP协议在纯Web环境HTML5中不被普遍支持尤其是在没有额外转码服务的情况下。因此流媒体转换是必经之路。我们将RTSP流转码为HLSHTTP Live Streaming协议其播放列表文件正是.m3u8。HLS的工作原理是将整个流切割成一系列小的、基于HTTP的文件TS分片并由一个M3U8索引文件来记录。浏览器的video标签原生支持HLS这使得它成为Web端直播和点播的事实标准。对于Unity WebGL我们虽然不直接使用video标签但AVPro Video在底层能够解析并播放这种通过HTTP获取的M3U8流。选择M3U8实质上是选择了一条Web兼容性最好的流媒体传输通路。2.4 数据可视化为什么是XCharts我们需要在视频画面上叠加实时数据例如在某个设备区域显示其温度变化曲线。Unity的UI系统UGUI虽然强大但制作动态、美观的图表需要大量开发工作。XCharts是一个基于UGUI的、功能强大的Unity图表库它支持折线图、柱状图、饼图、雷达图等多种类型且配置灵活、性能较好。它的优势在于其生成的图表本身就是UGUI的Canvas下的GameObject可以轻松地设置屏幕空间Screen Space渲染模式并放置在视频画面UI的上层。通过调整RectTransform和Canvas的渲染顺序我们可以实现图表“悬浮”在视频特定位置的效果。同时XCharts提供了丰富的API可以动态地增删、更新数据点非常适合实时数据的展示。2.5 整体架构流程图整个系统的数据流可以这样理解源端海康威视网络摄像机产生RTSP视频流。转码服务层关键中间件部署在服务器上的流媒体服务如Nginx with RTMP module, SRS, 或FFmpeg进程。该服务通过FFmpeg“拉取”摄像头的RTSP流并实时转码通常为H.264和封装为HLS格式生成M3U8索引文件和TS分片文件并通过HTTP服务暴露出来。客户端Unity WebGL应用网络请求Unity的UnityWebRequest向转码服务器请求M3U8文件。视频播放AVPro Video解析M3U8文件并持续请求TS分片解码后渲染到Render Texture。场景集成将该Render Texture赋值给3D模型材质或Raw Image UI显示视频画面。数据叠加XCharts图表作为独立的UI元素根据从其他数据接口如WebSocket、REST API获取的实时数据更新并定位到视频画面的指定坐标位置。这个架构清晰地将流媒体处理服务器端与客户端渲染、可视化浏览器端解耦各司其职保证了系统的可扩展性和稳定性。3. 核心模块实现与实操要点理论清晰后我们进入实战环节。每一步都有需要注意的细节。3.1 流媒体服务器搭建与配置这是整个项目的基石。没有稳定可靠的M3U8流后面一切都是空谈。我们以常用的Nginx nginx-rtmp-module方案为例。1. 服务器环境准备选择一台拥有公网IP或内网可访问的Linux服务器如Ubuntu 20.04。确保服务器带宽足够能够承载摄像头流的转码和分发压力。2. 编译安装Nginx与RTMP模块不建议直接使用系统仓库的Nginx通常需要自定义编译以加入RTMP和HLS支持。# 安装依赖 sudo apt-get update sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev # 下载Nginx和nginx-rtmp-module源码 wget http://nginx.org/download/nginx-1.22.1.tar.gz tar -zxvf nginx-1.22.1.tar.gz git clone https://github.com/arut/nginx-rtmp-module.git # 编译安装 cd nginx-1.22.1 ./configure --with-http_ssl_module --add-module../nginx-rtmp-module make sudo make install3. 配置Nginx支持HLS编辑Nginx配置文件通常位于/usr/local/nginx/conf/nginx.conf在http块内添加一个用于分发HLS片段的服务器块并在外层添加rtmp服务块。# 在events{}块之后添加 rtmp { server { listen 1935; # RTMP默认端口 chunk_size 4096; application live { # 应用名推流地址会用到 live on; record off; # 将收到的流转推为HLS hls on; hls_path /tmp/hls; # HLS切片文件存储目录 hls_fragment 2s; # 每个TS切片时长 hls_playlist_length 6s; # M3U8列表长度 # 下面这行很重要允许所有跨域请求否则WebGL无法加载 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; } } } http { server { listen 8080; # 提供HLS文件访问 location /hls { alias /tmp/hls; # 与rtmp中hls_path一致 # 以下头部对HLS在Web端播放至关重要 add_header Cache-Control no-cache; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Methods GET, OPTIONS; types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } } } }注意Access-Control-Allow-Origin头部必须正确配置为*或你的WebGL应用所在域名这是解决浏览器CORS跨域资源共享错误的关键。生产环境建议指定具体域名而非通配符*。4. 启动服务与推流启动Nginx后我们需要将海康摄像头的RTSP流“推”到这个RTMP服务上。使用FFmpeg在服务器上执行拉流转推ffmpeg -i rtsp://admin:yourpassword192.168.1.64:554/Streaming/Channels/101 \ -c:v copy -c:a aac -f flv rtmp://localhost:1935/live/camera1-c:v copy -c:a aac视频流直接拷贝假设是H.264音频流转为AAC格式FLV容器要求。rtmp://localhost:1935/live/camera1推流地址。live是配置中定义的application名camera1是流名称stream key。如果一切正常你将在/tmp/hls目录下看到生成的camera1.m3u8文件和一系列.ts切片文件。通过http://你的服务器IP:8080/hls/camera1.m3u8即可访问到这个M3U8流。实操心得延迟与参数调优hls_fragment和hls_playlist_length直接影响延迟。2秒的片段会产生至少2秒的延迟。对于实时监控可以尝试设置为1s但会更频繁地产生小文件增加服务器I/O压力。需要在实时性和性能间权衡。流稳定性网络波动可能导致FFmpeg拉流中断。建议使用-rtsp_transport tcp参数强制RTSP over TCP虽然效率稍低但更稳定。或者编写守护脚本在FFmpeg进程退出时自动重启。音频问题很多监控摄像头音频编码非AAC或者根本没有音频。FFmpeg推流时如果遇到不兼容的音频编码会失败。可以尝试-an参数禁用音频或者用-c:a libfdk_aac需编译时支持进行高质量转码。3.2 Unity项目中集成AVPro Video1. 插件导入与基础设置从Asset Store购买并导入AVPro Video。导入后建议先仔细阅读其自带的WebGL示例场景通常在AVProVideo-Samples/Scenes/目录下。2. 创建播放器在Unity场景中创建一个空GameObject命名为“VideoPlayerManager”。为其添加MediaPlayer组件和DisplayUGUI组件如果要在UI上显示。MediaPlayer组件这是核心控制器。Source选择Path因为我们通过URL加载。Path可以先留空后续通过代码动态赋值M3U8的URL。Auto Start根据需求勾选如果希望加载后自动播放就勾上。Loop是否循环播放对于直播流通常勾选。DisplayUGUI组件将视频渲染到UGUI的RawImage上。将其Media Player字段拖拽赋值给上面的MediaPlayer组件。在场景中创建一个UI - RawImage然后将这个RawImage对象拖拽到DisplayUGUI的Target字段。3. 编写播放控制脚本创建一个C#脚本HikvisionStreamPlayer.cs挂载到VideoPlayerManager上。using UnityEngine; using RenderHeads.Media.AVProVideo; public class HikvisionStreamPlayer : MonoBehaviour { public MediaPlayer mediaPlayer; public string m3u8Url http://your-server:8080/hls/camera1.m3u8; void Start() { if (mediaPlayer null) mediaPlayer GetComponentMediaPlayer(); if (mediaPlayer ! null) { // 监听事件了解播放状态 mediaPlayer.Events.AddListener(OnMediaPlayerEvent); // 设置播放路径并准备 mediaPlayer.OpenMedia(MediaPathType.AbsolutePathOrURL, m3u8Url, true); } } void OnMediaPlayerEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode) { switch (et) { case MediaPlayerEvent.EventType.ReadyToPlay: Debug.Log(视频已准备就绪可以开始播放。); mp.Play(); break; case MediaPlayerEvent.EventType.Started: Debug.Log(视频开始播放。); break; case MediaPlayerEvent.EventType.FirstFrameReady: Debug.Log(第一帧已渲染。); break; case MediaPlayerEvent.EventType.Error: Debug.LogError(播放错误: errorCode); // 这里可以添加重试逻辑 break; case MediaPlayerEvent.EventType.FinishedPlaying: Debug.Log(播放结束。); // 直播流通常不会结束如果是点播可以在这里处理 break; } } // 提供给UI按钮调用的方法 public void PlayStream(string url) { if (!string.IsNullOrEmpty(url) mediaPlayer ! null) { m3u8Url url; mediaPlayer.OpenMedia(MediaPathType.AbsolutePathOrURL, m3u8Url, true); } } void OnDestroy() { if (mediaPlayer ! null) { mediaPlayer.Events.RemoveListener(OnMediaPlayerEvent); } } }4. WebGL播放器设置这是最关键的一步直接影响最终能否在浏览器中播放。进入File - Build Settings选择WebGL平台点击Player Settings。Resolution and Presentation根据需求设置默认画布尺寸。如果希望全屏自适应可以取消勾选Run In Background并在代码中处理屏幕尺寸变化。Publishing SettingsCompression Format: 建议使用Brotli以获得更小的包体但需要Web服务器支持。回退方案选Gzip。Data Caching: 启用可以提升重复访问的加载速度。**最关键的部分在Player Settings - WebGL图标下找到WebGL Template**。AVPro Video为了其功能正常工作**强烈建议使用其自带的模板**。你可以在AVProVideo/Editor/Resources/目录下找到AVProWebGL模板文件夹。将其复制到你的项目Assets/WebGLTemplates/目录下。然后在Player Settings中选择AVProWebGL作为模板。调试在Publishing Settings中勾选Development Build和Autoconnect Profiler便于在浏览器控制台查看日志。实操心得模板的重要性不要使用Unity默认的WebGL模板。AVPro Video的模板包含了其JavaScript插件和必要的HTML/JS桥接代码这是视频解码和播放能正常工作的基础。忽略这一步会导致黑屏或功能异常。路径与URL在WebGL中MediaPathType选择AbsolutePathOrURL。确保你提供的M3U8 URL是可以通过浏览器直接访问的。在编辑器模式下你可能需要启动一个本地HTTP服务器来测试M3U8文件。内存与性能视频解码消耗大量内存。在Player Settings - WebGL - Memory Size中适当增加内存大小如256MB或512MB避免因内存不足导致崩溃。同时注意视频的分辨率过高的分辨率如4K在WebGL中解码压力巨大建议服务器端转码时适当降低分辨率如1080p或720p。3.3 集成XCharts实现数据叠加视频流能播了接下来就是在上面“画”图表。1. 导入与创建图表从Asset Store导入XCharts。在UI Canvas下创建一个空对象命名为“DataChart”。为其添加LineChart组件以折线图为例。2. 配置图表基础样式通过LineChart组件的Inspector面板进行快速配置Title设置图表主标题和子标题如“设备A温度监测”。Legend图例显示多条线时有用。X Axis/Y Axis配置坐标轴类型数值型、类目型等、刻度、标签格式。对于实时时间序列X轴可以设置为Value类型并在代码中动态更新范围。Series系列列表。点击“”添加一个系列可以设置线型、颜色、宽度、是否显示数据点等。3. 编写动态数据更新脚本创建一个脚本RealtimeChartUpdater.cs挂载到DataChart上。using UnityEngine; using XCharts; public class RealtimeChartUpdater : MonoBehaviour { public LineChart lineChart; public int maxDataPoints 50; // 图表上最多显示的数据点数量 private float timeCounter 0f; private float updateInterval 2f; // 模拟数据更新间隔 void Start() { if (lineChart null) lineChart GetComponentLineChart(); if (lineChart ! null) { // 确保至少有一个系列 if (lineChart.series.Count 0) { lineChart.AddSerieLine(); } var serie lineChart.series[0]; serie.symbol.show true; // 显示数据点 // 清空初始数据 serie.ClearData(); } } void Update() { // 模拟定时从网络API获取数据 timeCounter Time.deltaTime; if (timeCounter updateInterval) { timeCounter 0f; AddDataPoint(Random.Range(20f, 30f)); // 模拟温度数据 } } void AddDataPoint(float value) { if (lineChart null || lineChart.series.Count 0) return; var serie lineChart.series[0]; // 获取当前时间或数据序号作为X轴 float xValue serie.dataCount 0 ? serie.data[serie.dataCount - 1].x 1 : 0; // 添加新数据点 serie.AddXYData(xValue, value); // 如果数据点超过最大值移除最旧的点实现滑动窗口效果 if (serie.dataCount maxDataPoints) { serie.RemoveData(0); // 需要更新X轴的范围让图表看起来是向右滚动的 // 这里简化处理实际可能需要调整X轴的最小最大值 // lineChart.UpdateXAxisMinMax(serie.data[0].x, serie.data[serie.dataCount - 1].x); } // 刷新图表 lineChart.RefreshChart(); } // 一个公共方法用于从WebSocket或其他数据源回调中更新数据 public void UpdateChartWithRealData(float timestamp, float dataValue) { AddDataPoint(dataValue); } }4. 图表与视频画面的层级整合Unity UI的渲染顺序由Canvas下的层次顺序Hierarchy中的上下顺序和Canvas的Sort Order决定。确保图表的Canvas或父Canvas的Sort Order高于播放视频的Canvas。通常的做法是视频播放使用一个Render Mode为Screen Space - Camera或Screen Space - Overlay的Canvas。图表使用另一个独立的Canvas并将其Sort Order设置为比视频Canvas更大的值。通过调整图表UI元素的锚点Anchors和位置Pos将其定位到视频画面的特定区域如右上角。实操心得性能考虑频繁调用AddDataPoint和RefreshChart比如每帧会对性能造成压力。务必根据实际数据更新频率来调用例如每秒一次或当新数据到达时。上述例子用了Update模拟实际项目应使用协程、InvokeRepeating或事件驱动。数据绑定上述示例是模拟数据。真实项目中UpdateChartWithRealData方法应该被你的数据获取模块如WebSocket客户端、HTTP轮询回调所调用。图表样式XCharts的配置项非常丰富花时间调整网格线、背景色、文本样式等可以让图表与你的UI主题更融合避免显得突兀。交互功能XCharts支持工具提示Tooltip、数据区域缩放DataZoom等交互功能。在监控场景中可以考虑启用Tooltip当鼠标悬停在图表上时显示精确的数据值和时间点。3.4 WebGL构建与部署的专项优化将Unity项目成功构建为WebGL并部署到服务器才能让最终用户访问。这一步也有不少坑。1. 构建设置优化压缩格式如前所述优先选择Brotli。这需要你的Web服务器如Nginx支持并配置对.br文件的识别。如果不行就选Gzip。代码剥离Code Stripping为了减小构建大小可以启用Managed Stripping Level如设置为High。但要注意这可能会因为过度剥离导致运行时反射相关功能出错。如果发布后出现找不到类或方法的错误可能需要降低剥离等级或添加link.xml文件来保留必要的程序集。异常处理将Exception Support设置为Explicitly Thrown Exceptions Only可以减少代码量但会使得非显式抛出的异常如空引用难以调试。开发阶段建议用Full发布时可考虑调整。2. 部署服务器配置将构建生成的Build文件夹包含.html,.js,.data,.wasm等文件上传到你的Web服务器例如Nginx或Apache。 一个简单的Nginx静态站点配置如下server { listen 80; server_name your-domain.com; root /path/to/your/unity-webgl-build-folder; index index.html; # 以下MIME类型对于WebGL构建文件的正确加载至关重要 location ~ .*\.(js|wasm|data)$ { # 设置长时间缓存因为这些文件内容哈希化内容变文件名就变 add_header Cache-Control public, max-age31536000, immutable; # 对于wasm文件需要正确的MIME类型 types { application/wasm wasm; application/octet-stream data; application/javascript js; } } # 对于主HTML文件通常不缓存或短时间缓存 location /index.html { add_header Cache-Control no-cache, no-store, must-revalidate; } # 同样需要CORS头部如果从不同域加载视频流 location / { add_header Access-Control-Allow-Origin *; } }3. 解决WebGL上下文创建失败这是一个常见的运行时错误浏览器控制台可能提示A WebGL context could not be created. Reason: Could not create WebGL context.。浏览器硬件加速确保用户浏览器的硬件加速已开启。这是最常见的原因。显卡驱动用户显卡驱动过旧或不支持WebGL 2.0。可以在Unity Player Settings中尝试将WebGL 2.0回退到WebGL 1.0但某些图形功能可能受限。内存不足如前所述增加Memory Size。尤其是在播放高清视频时。安全上下文WebGL的一些高级功能如SharedArrayBuffer要求页面运行在安全上下文HTTPS中。如果你的应用部署在HTTPS下但引用了HTTP资源如M3U8流也可能出现问题。尽量保证所有资源网页、视频流都使用HTTPS。4. 移动端与横屏适配如果需要在移动端浏览器或Pico等VR设备浏览器中访问需要考虑横屏设置。Unity端在Player Settings - Resolution and Presentation中将Default Orientation设置为Landscape Left或Auto Rotation。HTML模板端修改AVPro Video的WebGL模板index.html中的meta nameviewport标签并添加JavaScript来检测和锁定屏幕方向。CSS适配确保Canvas元素能够根据屏幕尺寸自适应。AVPro Video的模板通常已包含相关CSS但你可能需要根据自己UI布局进行调整。4. 常见问题排查与性能调优实录在实际开发和部署中我遇到了不少问题这里总结一下希望能帮你绕过这些坑。4.1 视频流相关问题问题1视频黑屏但控制台没有明显错误。排查步骤检查M3U8 URL首先直接在浏览器地址栏输入你代码中设置的M3U8 URL看是否能下载到一个文本格式的M3U8文件。如果不能说明服务器地址、端口、路径或CORS配置有误。检查CORS打开浏览器的开发者工具F12切换到Network网络选项卡刷新Unity WebGL页面。查看对M3U8文件和.ts文件的请求状态。如果状态码是200但被CORS policy阻止控制台会有明确的CORS错误信息。这必须回到Nginx配置中确保Access-Control-Allow-Origin等头部正确设置。检查AVPro Video日志AVPro Video在WebGL上会将内部日志输出到浏览器控制台。查看是否有“Failed to load”、“Decoder error”等信息。确保你使用的是AVPro Video的WebGL模板。检查视频格式虽然HLS主流编码是H.264AAC但确保你的转码输出确实是浏览器和AVPro Video支持的格式。可以用ffprobe工具分析一下生成的TS文件。问题2视频播放卡顿、延迟高。原因与解决网络带宽不足这是首要原因。检查服务器出口带宽和客户端网络。降低转码的输出码率和分辨率如使用FFmpeg的-b:v 1000k参数限制视频码率。HLS切片参数hls_fragment设置得太长如10秒会导致初始加载和追延迟很高。设置为1-2秒为宜。hls_playlist_length也应相应缩短。客户端解码性能WebGL中视频解码依赖浏览器和WASM性能。过高的分辨率如4K可能导致解码跟不上。在服务器端将视频缩放至1080p或720p。播放器缓冲AVPro Video可能有缓冲设置。检查MediaPlayer组件的Buffer相关属性适当减小缓冲大小可能降低延迟但会增加卡顿风险。问题3音频不同步或没有声音。排查首先确认摄像头源是否有音频以及FFmpeg推流时是否正确处理了音频-c:a aac。在Nginx配置中确保HLS切片包含了音频流。在Unity中检查MediaPlayer组件的Audio Output设置是否正确以及场景中是否有有效的Audio Listener。4.2 Unity WebGL构建与运行问题问题4构建后在浏览器中运行时提示“Unable to parse Build/xxx.framework.js.gz”等加载错误。解决这通常是Web服务器没有正确配置.gz或.br压缩文件的MIME类型或者没有启用静态压缩。确保服务器能正确识别.js.gz,.js.br,.data.gz,.wasm.gz等文件并在请求时返回正确的Content-Encoding头。参考前面的Nginx配置或查阅你所用Web服务器的Gzip/Brotli静态压缩配置文档。问题5在Chrome中运行正常但在某些浏览器如奇安信、旧版Edge中白屏或报WebGL错误。解决首先检查这些浏览器是否支持WebGL。可以访问https://get.webgl.org/进行测试。如果支持但仍出错可能是浏览器安全策略、插件冲突或GPU黑名单导致。尝试更新浏览器、禁用所有插件。在Unity构建时尝试降低图形API级别如从WebGL 2.0降到1.0。这类问题有时难以彻底解决需要在应用入口给出清晰的浏览器兼容性提示。问题6内存增长导致最终崩溃。调优监控内存使用Unity ProfilerWebGL远程连接或浏览器的Memory工具监控内存使用。释放资源确保在场景切换或对象销毁时正确释放AVPro Video的MediaPlayer调用CloseMedia()和Destroy()。XCharts的数据列表如果无限增长也要定期清理。纹理尺寸视频渲染纹理Render Texture的分辨率不要设置得远高于实际显示尺寸。构建优化启用Code Stripping移除未使用的引擎模块在Player Settings - Publishing Settings - Managed Stripping Level 和 Optimization下配置。4.3 XCharts叠加显示问题问题7图表显示在视频后面被遮挡了。解决这是UI渲染层级问题。确保图表所在的Canvas的Sort Order大于视频显示UI所在的Canvas的Sort Order。同时检查两个Canvas的Render Mode确保它们都在相同的渲染空间如都是Screen Space - Overlay。问题8图表更新导致整体卡顿。解决降低刷新频率不要每帧都调用RefreshChart()。使用数据队列累积一定数据或固定时间间隔如0.5秒刷新一次。简化图表减少数据系列数量、关闭不必要的视觉特效如动画渐变、简化Tooltip的显示格式。数据量限制图表上显示的最大数据点数量如上述代码中的maxDataPoints避免绘制过多元素。问题9如何根据视频中某个物体的位置动态定位图表思路这需要将3D世界坐标转换为2D屏幕坐标。假设你有一个3D物体比如设备模型你想在它的上方显示其数据图表。在代码中获取该物体在世界空间中的位置然后使用Camera.WorldToScreenPoint方法转换为屏幕坐标。将这个屏幕坐标Vector3z分量忽略转换为UI的局部坐标。可以使用RectTransformUtility.ScreenPointToLocalPointInRectangle方法。将图表的RectTransform的anchoredPosition设置为转换后的坐标。你需要每帧或在物体移动时更新这个坐标。注意如果视频画面是全屏UI那么用于转换的Camera应该是UI Camera如果是Screen Space - Camera模式或主相机如果视频是渲染到3D物体上。这套从服务器搭建到客户端集成的方案经过多个项目的打磨已经能够稳定支撑工业监控可视化场景。核心在于理解每个环节的作用与限制服务器负责高效的流转换AVPro Video攻克了WebGL下的播放难题而XCharts则提供了灵活的数据呈现能力。把它们串联起来你就能在浏览器的3D世界里打造一个功能强大的实时监控与数据分析平台。
返回列表