Skip to content

XMapEngine 三层架构重构

将小鹏一张图的 SR 渲染引擎从“能跑但难扩展”的单体结构,改造成职责清晰、能承接手势交互和地图状态演进的三层架构。

交互延迟1 帧 → 0 帧
架构层级Core / Services / Tools
依赖治理ServiceContainer / DI

背景

XMapEngine 是小鹏一张图 SR 渲染链路中的核心模块,承接节点树、地图状态、相机控制、手势交互和跨端消息。入职初期通读代码时,最大的风险不是某个 bug,而是系统边界已经开始模糊:手势识别、地图状态管理、相机控制互相直接调用,新增功能会牵动多个模块。飞书工作总结中把这条线进一步归纳为 ServiceContainer + DI/IoC 的依赖治理问题,本质是让模块依赖显式化、可替换、可审查。

当时业务还在快速迭代,V5 交互、回自车、LD/SD 切换、车模大小补偿等需求都要进入同一条链路。如果继续在单体结构里叠逻辑,后续每次改手势或镜头都会变成全局风险。

问题

问题表现风险
职责堆叠手势、地图状态、渲染控制在同一层互相调用新增功能需要跨模块改动
状态分散比例尺、相机高度、图层切换散落在多个类回自车和切换场景容易抖动
扩展困难新手势和新镜头行为缺统一入口每次迭代都要重新理解调用链
依赖隐式服务对象和工具对象到处被直接拿取测试、替换、灰度和回滚成本都变高

约束

  • 线上链路不能大拆大换,必须在业务迭代中逐步替换。
  • Android 原生层和 Unity 层各有一套手势识别,行为要统一。
  • 地图比例尺、相机高度、车模显示和 LD/SD 切换存在耦合,不能只做代码分层。

方案

重构目标不是“为了三层而三层”,而是把变化点放到正确位置。

text
Core
  节点树管理 / 生命周期 / 事件总线

Services
  ServiceContainer / 手势服务 / 地图状态服务 / 相机服务 / 图层服务

Tools
  坐标转换 / 动画工具 / 日志工具 / 调试辅助

关键设计包括:

  • 手势策略化:单指拖拽、双指缩放、双击、惯性甩图等 8 类手势独立实现,通过统一接口接入。
  • 回自车状态机:把 start、ing、end 三态显式化,降低车模、比例尺、相机高度之间的隐式耦合。
  • LateUpdate 对齐:LD 地图移动统一在 OnLateUpdate 对齐手势,避免视觉错帧。
  • 服务上提:地图状态和相机状态不再散在工具类里,由 Services 层统一协调。
  • 依赖容器化:用 ServiceContainer 承载核心服务注册和获取,把“谁依赖谁”从隐式调用改成可审查的依赖关系。

产出

  • XMapEngine 分层架构图和节点树说明。
  • 手势接口化改造方案。
  • ServiceContainer 和 DI/IoC 依赖治理方案。
  • IMapEngine 抽象和对接文档。
  • 地图状态、相机状态、跨端消息的调用时序图。

效果

这次重构直接支撑了后续几个高频场景:

  • 拖拽错 1 帧问题最终被抹平到 0 帧延迟。
  • 回自车视觉抖动问题有了状态机承载点。
  • V5 车模大小、手势轻扫、比例尺对齐不再只能靠局部补丁。
  • 新服务可以先进入容器和接口,再逐步替换旧调用点,降低边做业务边重构的风险。
  • 后续工程文档可以围绕 Core / Services / Tools 讲清楚模块边界。

可复用方法论

  1. 先找变化点,再命名分层。
  2. 状态问题不能只靠工具类解决,必须有拥有者。
  3. 交互系统要同时看输入、状态、渲染时机,不能只看手势识别。
  4. 架构文档不是收尾材料,而是重构过程中的同步工具。

复盘

这篇案例的价值不在于“三层架构”这个名字,而在于它把一个持续变化的业务引擎从经验维护变成可讨论、可扩展、可交接的系统。下一轮补充资料时,应优先从飞书文档中拉取架构图、对接文档和评审记录,脱敏后补入图表。

企业级技术案例库 · 内容先审计再发布