简介这份AR室内导航Demo是一套基于Unity3D与Vuforia SDK构建的工程源码包主要面向Unity开发者、AR初学者及LBS位置服务研究者。项目将增强现实与室内定位结合利用平面图、二维码或标志物作为Vuforia识别目标实时叠加虚拟路径和指向信息同时借助GPS、Wi-Fi或蓝牙信标感知用户位置适合用于毕设、课设、技术验证或商业原型参考。压缩包共856个文件、62.46MB除场景、脚本、资源、配置和文档等常规模块外还细分出450个meta元数据、181张jpg贴图、60个cs脚本、18个prefab预设、25个mat材质、13个xml配置及Android/iOS构建依赖目录清晰便于定位代码与资源。已有5707人浏览学习。通过研读核心脚本和场景组织可掌握AR目标识别、路径计算、交互反馈及Vuforia配置的整套实现思路并可直接在此基础上扩展新的导航算法或优化界面呈现。 在地铁站或者大型商场里掏出手机打开地图App蓝点显示你在大楼正中可你分明站在楼梯口——这是每个室内导航开发者都听过的抱怨。GPS信号在室内被混凝土墙和金属结构反射得支离破碎室外地图那套“蓝色圆点路径线”放在室内基本失效它没法告诉你“该不该拐弯”“是不是走过了”。我花了两个月从零搭了一个AR室内导航Demo把仓库二楼从CAD图纸变成了手机屏幕上贴地的3D箭头。这篇文章把完整过程拆开讲清楚技术栈怎么选、模块怎么分工、核心代码怎么写、哪些坑我踩得最惨。如果你正准备上手AR应用开发或者在做室内位置服务相关的项目这篇应该能帮你省下不少调试时间。1. 为什么室内导航必须换一个交互思路1.1 室内环境的三个天然劣势先别急着谈AR得先弄明白室内导航为什么难。室外导航能跑通本质上靠的是GPS、基站和地图数据的配合。可室内环境里GPS信号基本被建筑结构挡掉了即使能收到误差也在几十米量级。Wi-Fi定位虽然能辅助精度也就三到五米在楼层里几乎是靠运气。这是第一层障碍没有一套可靠的绝对位置信号源。第二层障碍是地图表达方式。室内地图不是简单的经纬度加道路它有楼层、有墙体、有柜台、有门禁这些信息在传统矢量地图上要么被简化成色块要么干脆不画。你在用户面前放一张2D平面图他能看懂实验室的布局图可一旦站在商场中庭朝北看平面图上“上北下南”的方向感瞬间崩塌。第三层障碍是人的方向感。室内没有蓝天白云做参照也没有地标性的高楼转个身就分不清东西南北。传统地图给一个“转向提示”用户还得把手机上的地图朝向和自己身体的朝向做一次空间换算这一步已经劝退大量用户。AR完全绕开了这个换算过程虚拟箭头直接铺在你脚下的真实地板上告诉你“往那边走”不需要再脑补地图朝向。1.2 AR解决的是“最后一米”的认知负担我做Demo时发现一个很有意思的现象用户在熟悉的走廊里基本不需要导航真正会迷路的是从电梯口出来、从会议室出来、或者第一次到这个楼层的那一刻。传统导航的蓝点能告诉你“你在这”但给不出“你面朝哪”的强反馈。AR的价值在于把导航提示从“二维抽象符号”变成“三维空间锚定物”。一支贴地的半透明箭头实际就是一个锚定在真实地面上的虚拟物体用户能直观感知箭头指向的方向、与自己的距离、以及下一个拐弯点在哪。加上手机摄像头实时透出真实环境用户余光还能看到周边店铺、障碍物不容易走着走着撞上货架。这也是我自己实测下来AR导航相比纸质地图和2D手机地图体验提升最大的地方。2. 技术栈选型实录ARFoundation、Beacon与IMU的取舍2.1 AR渲染框架怎么选Demo阶段不需要考虑大厂那种自研引擎的复杂路径重点是在三个主流方案里做选择原生的ARKit、原生的ARCore以及跨平台的ARFoundation。我当时由于要同时覆盖Android和iOS测试机直接选了ARFoundation。它在Unity里统一封装了ARKit和ARCore的底层面容大部分API可以一套代码跑两端缺点是它只做AR渲染和平面识别定位相关的核心逻辑还是得自己写。如果只做单端Demo直接上ARKit或ARCore原生的API会更省事稳定性也更好。但凡是有一点跨平台需求我建议一开始就用ARFoundation不然到后期把整条逻辑链从Android迁移到iOS非常痛苦我在Demo中期的确踩过这个跨端改代码的雷。2.2 定位方案Beacon、VIO、视觉地标怎么组合室内定位方案有好几条路线选型直接影响Demo的落地效果和复杂度。方案精度部署成本优缺点蓝牙Beacon1~3米低买十几个Beacon即可精度一般但部署简单可做绝对定位修正视觉VIOARCore/ARKit自带相对位姿较准零成本纯算法短距离好使长时间会漂移无法确定绝对位置视觉地标匹配亚米级中需要拍摄大量参考图精度较高但光照和环境变化会影响识别UWB超宽带厘米级高需要布设基站精度最高适合对成本不敏感的场景我的Demo最终采用Beacon 视觉VIO融合的方案。核心思路很简单ARCore和ARKit内置的VIO负责短时间内的稳定性提供平滑的位姿变化Beacon负责提供“绝对坐标”在用户走了一段路之后把漂移拉回来。视觉地标匹配我放在后期扩展里做因为Demo阶段先不引入图像特征库那需要采集大量现场照片时间成本太高。2.3 传感器数据的处理思路Beacon广播的是RSSI信号强度不能直接当距离用。业界常用的换算公式是d 10^((A - RSSI) / (10 * n))其中A是1米处测到的参考信号强度通常在-59dBm到-65dBm之间n是环境衰减因子室内有遮挡时取2.5到3.5比较合适。这个公式算出来的距离噪声很大人一挡、门一关RSSI能跳十几dBm。所以我在采样层加了一个滑动窗口滤波取最近5次扫描值的平均值再用卡尔曼滤波做平滑。刚开始我只用均值结果Beacon定位点像喝醉了酒一样在走廊里来回漂滤波结构加上之后才基本稳定在可用的状态。3. Demo架构拆解地图数据、定位引擎、AR渲染三层分工3.1 地图数据层是整套系统的心脏一个可靠的导航系统一定不能把地图写死在代码里而是独立成一个数据文件。我用了一个JSON文件存储所有地图信息包含楼层号、节点表、边表、POI表和不可通行区域。节点表描述路径上的关键折点边表描述哪些节点之间有通路POI表描述用户的起点和终点位置。{ floor: 2, nodes: [ {id: N01, x: 2.5, y: 3.0, type: corridor}, {id: N02, x: 12.0, y: 3.0, type: corridor}, {id: N03, x: 12.0, y: 8.0, type: corridor} ], edges: [ {from: N01, to: N02, weight: 1.0}, {from: N02, to: N03, weight: 1.0} ], pois: [ {id: P01, name: 电梯口, x: 0.5, y: 0.8}, {id: P02, name: 仓库大门, x: 12.5, y: 8.5} ] }这里有个很重要的细节所有坐标必须是米制局部坐标且保持同一个原点。我用的CAD原始图纸单位是毫米直接读进Unity之后一个箭头模型被缩放到图纸尺寸的千倍差点把摄像机怼进模型内部。后来我在数据加载层统一做了毫米转米并且规定整个Demo只用局部坐标系不引入经纬度大幅减少了换算出错的可能。3.2 定位引擎把传感器数据变成“我在哪”定位引擎层的职责很简单接收Beacon扫描数据和ARFoundation传出的设备位姿输出一个统一的用户位置对象。这个对象包含用户在地图坐标系下的x、y坐标以及朝向角度yaw。融合逻辑大致是这样每次收到新的Beacon数据用滤波后的RSSI算出到各Beacon的距离再用三边定位解算出当前位置这个位置如果和VIO推测的位置差值大于一定阈值就判定发生了漂移系统把VIO的参考坐标系重新拉回到Beacon定位结果附近。实际实现里我并没有做特别重的图优化而是直接用了一个加权平均VIO输出权重0.7Beacon输出权重0.3短期跟踪以VIO为主长期修正靠Beacon。3.3 AR渲染和交互层这一层在Unity里承担两件事第一把路径拼成3D模型放到真实世界上第二响应点位切换和用户到达事件。路径渲染我用的是LineRenderer把路径节点转换到AR世界坐标之后生成一条贴地的折线。为了视觉上更像是导航而不是画线我在每条路径段上等距放置箭头模型箭头朝向下一段路径的方向。当用户当前位置距离当前导航点小于1.2米时触发“到达该点”事件将导航目标切换为路径上的下一个点同时更新箭头的朝向。界面部分只保留了一个顶部Text显示下一目标点名称和剩余距离。一开始我加了一堆按钮和面板实测发现走路时根本没法点按AR导航界面越简单越好这是很多Demo容易犯的过度设计错误。4. 核心实现链路从平面图到脚下3D箭头的关键代码4.1 地图加载与坐标转换地图加载之后第一步要把JSON里的节点坐标从局部米制坐标转换到AR世界坐标。ARFoundation的ARSession启动时世界原点通常设在Session开始时设备所在位置这个位置和地图原点没有必然关系。我采用的做法是用户到达一个已知坐标的起点比如电梯口长按屏幕完成“锚点校准”这时系统记录下设备在AR世界中的位姿反推出地图坐标到AR世界坐标的变换矩阵。坐标变换公式就一行Vector3 worldPos someAnchor.TransformPoint(new Vector3(mapPos.x, 0, mapPos.y));这里someAnchor就是校准锚点。只要保证起点位置足够准确后面整条路径都会跟着准确。所以我在Demo里特意在电梯口放置了一个醒目的二维码用户扫码完成锚点初始化比手动输入坐标靠谱得多。4.2 路径规划A*还是BFS路径规划这部分因为地图规模不大直接用A*算法就能跑得很流畅。我维护了节点的邻接表和边权重启发函数用欧氏距离估算剩余代价。private float Heuristic(Node a, Node b) { return Vector2.Distance(a.position, b.position); }每次用户选择目的地之后A*在节点图上找到一条最短路径返回一个节点数组。值得强调的是路径规划在Demo里跑一次就够了不用每帧重算只有当用户明显偏离原路径比如走到障碍物那边时才重新规划。偏离检测我用的策略是计算用户到当前路径段的垂直距离连续5秒超过1.8米就判定偏离。实际操作中还有一个体验细节规划出来的路径是一堆折线从电梯口到仓库大门中间可能有二十几个节点直接沿着节点连线的方向放箭头用户会看到箭头一直细微抖动。要做一次路径抽稀把夹角特别小、距离特别近的节点合并掉只保留显著拐弯的节点。4.3 箭头跟随与转向提示箭头摆放在路径上之后接下来要处理的是“用户走到哪、箭头怎么变”的问题。我把路径看成一系列待到达点用户初始状态时目标点是路径的第一个节点。每帧玩家位置更新后计算玩家位置到当前目标点的水平方向向量把最靠近玩家的箭头模型旋转到这个向量的方向上。public void UpdateArrowDirection(Vector3 playerPos) { Vector3 toTarget currentTarget.position - playerPos; toTarget.y 0f; if (toTarget.magnitude arriveDistance) { MoveToNextTarget(); return; } guideArrow.rotation Quaternion.LookRotation(toTarget); }转向提示的做法是在两个路径段夹角超过30度的节点处额外放置一个大的转向箭头模型并配合文字提示“前方左转”。文字提示放屏幕中央偏上因为放太靠下会被手指或摄像头取景框底部遮挡。4.4 Beacon标定流程Beacon定位要跑得准标定不能省。我的标定流程是在每个Beacon布放点记录10秒内的RSSI数据取中位数作为该点实测值然后用工具箱把环境中已知位置的几个测试点分别测量距离反推A值和n值。这个反推可以用最小二乘法拟合最简单的方式就是直接拿两个已知点列方程解出来。为了让信号衰减模型在真实环境更准确我按不同区域分别拟合了一组A/n参数距离计算前根据最近Beacon所在区域选择参数。这套流程多花了半天时间但定位精度从四五米提升到了两米出头值了。5. 实测中的翻车现场坐标系错乱、漂移与遮挡5.1 坐标系错乱箭头全部飞天入地第一次跑通Demo时我在测试场地里发现路径箭头全都不在走廊上有的悬挂在半空有的直接穿入地面以下。排查链路是这样的先打印路径第一个节点的世界坐标发现Y值明显异常有的节点y$-0.8$有的y$3.2$。这说明地图坐标转换到AR世界坐标时Y轴出现了问题。检查后发现我在Unity中把地图的XZ平面映射到了AR世界的XZ平面本意是正确的用地面作为水平面但JSON里存的xy实际上是CAD图纸的横向和纵向而Unity中横向是X、纵向是Z我一开始直接读了mapPos.y出来放到Unity的y上等于让地面坐标变成了高度值。修复方式很简单加载地图节点时做一次轴向重映射取x作为Unity的X取y作为Unity的Z统一设置高度为0.05米略高于地面避免与地面重叠闪烁。5.2 VIO漂移走了30米后箭头越来越歪ARCore和ARKit的VIO在小范围移动时非常准但我把测试路线拉长到80米之后明显的漂移就出现了。具体表现是走完半条走廊后箭头指向依然正确但位置已经偏离真实路径左侧或者右侧好几米。这是惯导类算法的通病长时间积分导致误差累积。我的修正措施是在走廊两端各布一个Beacon当用户靠近Beacon时计算真实定位结果与当前VIO位置的偏差然后做一次平滑校正。需要注意的是不能直接硬切坐标否则VR画面会突然抖一下。我用的是将偏差在0.5秒内线性插值到当前位姿上过渡完用户不会有明显眩晕感。5.3 虚拟箭头穿墙视觉上非常出戏AR导航绕不开遮挡问题。虚拟箭头画在地面上当路径转弯点附近有一面玻璃墙或者半隔断箭头会直接穿过这些真实障碍物看起来就像把墙变成了透明。Demo阶段的优化方案是在不可通行区域的边界放置一层极薄的透明碰撞体然后用射线检测箭头是否穿过碰撞体穿过则降低箭头透明度或隐藏该段箭头。这个方法的缺陷是碰撞体需要手工摆放适合测试场地不大的Demo如果要做大型商场得用真实地图的障碍物多边形自动生成碰撞体。这个翻车过程给了我一个启发AR体验最大的敌人不是技术做不到而是“看起来不合理”。哪怕定位精度再高只要虚拟物体和真实世界的空间关系出现一丝违和用户就会觉得这东西不可靠。6. 从小Demo到可落地VPS、楼层切换与多人场景的扩展思路6.1 VPS视觉定位是把Demo推向产品级的必经之路Beacon定位在小范围场地够用但要在整层楼、整栋楼里部署Beacon的数量和维护成本会让人头疼。更稳妥的方案是VPS视觉定位提前拍摄场地内大量特征明显的照片建立视觉特征库用户举起手机扫描周边环境系统通过图像检索定位出手机在场景中的精确位姿。ARCore的Cloud Anchor本质上就是一套云端的VPS方案能够把虚拟内容和物理空间对齐到厘米级。我做Demo时没有把VPS完整做进去因为现场采集照片和标定工作量大。但如果你的项目场景固定、改造少VPS配合3D场景重建比如用3D Gaussian Splatting把室内场景重建出来定位精度和视觉一致性都会远超Beacon方案。这会是室内AR导航后续最值得投入的方向。6.2 楼层切换与跨层导航单层Demo跑通之后下一个自然需求就是楼层切换。跨层导航在室内环境里比室外复杂得多因为垂直方向的定位目前没有特别成熟的通用方案。我在设计里用了一个折中办法在楼梯口和电梯口放置二维码用户扫码后直接切换楼层地图并弹出“您已进入3楼”的确认。气压计检测可以作为辅助手段它能感知几个米级别的高度变化但受空调和门窗开闭影响较大不能作为唯一的楼层切换依据。6.3 与真实业务结合的几个方向如果手里有项目要做成产品我建议优先考虑这几个方向仓储拣货路径指引、会展观众动线引导、医院就诊科室导航。它们有一个共同点路径相对固定、容量可控、对实时性的容忍度高。我这次Demo来自仓库场景工人戴着AR眼镜或举着手机找货位比在PDA上翻列表找货位直观得多。另外AR眼镜的光学方案棱镜和光波导这几年越来越成熟等硬件重量和续航再往前一步这种导航形态会先在B端场景普及。现在的技术栈更新速度很快鸿蒙生态的AREngine、Kotlin侧的Compose实现、各种新的三维重建工具层出不穷但核心的定位融合、路径规划、姿态估计这几块逻辑是通用的。只要把架构设计好底层框架的替换只是时间成本问题。我的建议是如果你也打算做AR室内导航先不要急着追求大而全。把单层、单路由、单用户跑通把坐标系、滤波、路径生成这些基础功做扎实比盲目加功能有用得多。这个Demo做完之后我最大的体会是——AR导航真正难的不是渲染和识别而是把不完美的传感器数据安抚在一条“看起来合理”的路径上。这种工程上的手感比任何算法选型都重要。本文还有配套的精品资源点击获取