这是《数字展厅 Unity 项目开发实战分享》系列的第一篇,聚焦景区导视导航一体机。这类项目软硬结合、现场交付、内容长期更新——在没法重装、没人会改代码的现场,设备也得长期稳定跑下去。下面按整机链路、外配项与现场问题,把这一方向踩过的坑和攒下的办法整理出来。文中涉及的后台地址、服务凭据、设备 IP 一概不展开。
一体机要立在景区里:游客不培训就能用,运维不懂 Unity 也能改内容。程序由两个场景串起来——Scenes/Regist.unity(注册登录)与 Scenes/Map.unity(导航主场景),另有 Scenes/Test.unity 备用。配置与数据全部放在 StreamingAssets 下,随包拷贝、路径可读,运行时直接读文件。外设包括 3 块 LED 屏、3 个机械臂(下/中/上,共用一个串口)和系统 TTS 语音播报,点位数据 66 条。
把整机按链路来理解,排查问题时能快速定位到哪一环:
| 链路 | 触发源 | 关键脚本 | 结果 |
|---|---|---|---|
| 注册链路 | 启动自动 | Register.cs → MQTT.cs | 取 MAC 作设备 ID,注册或上线后载入 Map |
| 点位刷新链路 | 后台 MQTT 推送 | UIManager.OnMsg → PointsManager.SwitchPoint | 界面点位更新 + 资源下载 + 写回本地 JSON |
| 导航链路 | 游客点击 | PointsInfoConent / SurveyingAndMappingComponent / InfoShowPanel | 详情播报 + 虚线路线 + LED 三屏推送 + 机械臂转向 |
| 待机链路 | 360s 无操作 | UIManager.Update → Standby.cs | 图片/视频轮播,点击回地图 |
| 运维链路 | 人工操作 | QRCode / Time_Weather / DebugModel | 二维码取件、时间天气、调试面板 |
问题:一套包发到多台设备,设备身份怎么区分?
取网卡 MAC 地址转小写作为设备唯一 ID,注册态写进 PlayerPrefs;服务端以设备 ID 作为专属订阅主题,后台就能对单台设备定向推送,"一份包、多设备、不同内容"成立。代价是设备换网卡需要重新注册。
问题:交付后改内容要重新打包。
把能外配的全部外配到 StreamingAssets:config.txt(台号与二维码内容)、mqttConfig.json(通信参数)、LEDConfig.txt(三块屏地址、清屏间隔、欢迎语)、PortConfig.txt(串口号,当前 COM1 / 9600)、AngleConfig.txt(机械臂角度基准)、CarouselText.txt(滚动字幕)。改文本、重启程序即生效;这类文件启动只读一次、不热加载,所以"改完没生效"的第一反应应该是"重启了吗"。
问题:无人值守时的边界情况太多。
待机设成 360s 无操作进入图片/视频轮播,任意点击退出;OnResetTime() 统一负责重置待机计时与 LED 刷新计时,弹层、二维码、地图拖动都会回调它,避免"用着用着突然进待机"。退出程序与打开机械臂/LED 调试面板都藏在连点 8 次里(退出要求 2 秒内点满 8 次),把危险操作和日常交互彻底隔开。
问题:地图一缩放,点位和虚线就变形。
把点位图标、路线虚线登记为"不跟随缩放"的对象,在 RoutePointSize 里按当前缩放取逆缩放,视觉尺寸恒定;画虚线时同样按逆缩放生成每段 Image。另外 1 倍缩放时禁止拖拽,避免把地图拖出边界后找不到北。
问题:语音播报和背景音乐打架。
点位介绍走系统 TTS,和 Unity 的 BGM 是两套音量体系,叠加会听不清。播报前调 LowerVolume() 把 BGM 压低,用协程轮询播报状态,结束后 RestoreVolume() 恢复,OnDisable 里再兜一次防音量卡在低档。遗留隐患:待机轮播的视频自带音轨,与 BGM 可能叠加,还得单独处理。
回头看这一方向,能沉淀成方法的其实就一条:能外配的绝不写死,让内容更新不依赖开发。都不是什么高深技术,但都是被现场问题反复教育出来的。
(内容由AI生成,仅供参考)