Unity + EasyAR 跨平台 AR 发布与录屏踩坑全记录 最近把一个 Unity EasyAR 开发的 AR 项目同时发布到 Android 和 iOS整体流程走完最大的感受是AR 功能本身没有想象中复杂真正消耗时间的地方几乎全集中在环境配置、权限、打包参数和录屏细节上。我做的是图片识别触发类的 AR 应用通过识别图中的特征点加载 3D 模型和视频同时还需要在识别到内容后一键录屏分享。EasyAR 在这块正好带了 recording 模块但文档写得非常精简很多参数只能靠实测验证。这篇文章我按实际开发顺序来写选型、环境配置、Android 发布踩坑、iOS 发布踩坑、EasyAR recording 录屏用法与问题排查。标题里说的“图文详情”我尽量把每个问题发生的菜单位置和面板选项写出来方便对照自己的工程一步步查。如果你也在做跨平台 AR或者正在为录屏功能发愁这篇可以直接当一份排障手册用。1. 为什么用 Unity EasyAR以及我在选型时看重的点1.1 多端一致性与接入成本项目一开始就要求同时支持 Android 和 iOS。如果走原生路线相当于要维护两套完全独立的 AR 实现一套基于 Android 平台的 AR 能力一套基于 iOS 平台的 AR 能力两边的相机权限、追踪逻辑、模型加载方式都对不上开发周期直接翻倍。Unity 在这里的优势很明确一套 C# 业务逻辑AR 识别、模型播放、UI 交互、录制上传全都可以共用。EasyAR 相比原生方案最大的价值是把多端差异封装成了统一接口。同一个识别图配置同一份相机渲染逻辑在 Android 和 iOS 上只要打包出来就能跑。它不像原生 AR 那样需要依赖系统级的深度传感器或者特定的机型能力只要手机摄像头能用基本都能跑这对面向大量普通用户的 AR 应用来说很重要。选型时我还考虑过一个问题就是后续如果要换掉底层 AR 能力业务代码能不能少改动。用 EasyAR 的话识别图、场景结构、相机控制都是围绕它的接口组织的如果有一天要迁移到别的 SDK只需要替换底层调用部分UI 和业务逻辑不用大动。这一点在项目早期看不出来等项目变大后会省非常多事。1.2 License、Key 与工程导入细节EasyAR 的接入流程走的是开发者后台注册加 SDK 包导入的路子。包体拿到手后里面通常会有基础运行时、图像跟踪、平面检测、录屏等模块导入 Unity 工程时不要一股脑全塞进去建议只导入当前项目用到的模块否则工程会多出很多用不上的示例场景和依赖打包体积也会变大。我第一次导入时就把所有示例都勾了结果 Unity 工程里多了十几个 Demo 场景编译时间肉眼可见地变长。后面重新建工程只导入运行时和 ImageTarget 模块再手动复制一个识别示例场景来改造干净很多。许可证 Key 是另一个容易踩的坑。EasyAR 的 Key 要在配置面板里填进去而且不同模块可能需要不同的 Key 授权。比如基础图像识别用基础权限录屏功能可能要单独确认是否在授权范围内。我遇到过填了 Key 但没勾选对应模块权限的情况表现就是编辑器里一切正常打包到真机上录屏按钮点了没反应。这里建议在工程刚开始时就确认最终要用的模块清单提前在开发者后台配好 Key把 Key 填到 EasyAR 配置面板后先用官方示例场景跑一遍识别和录屏确认授权没问题再写业务代码。否则等业务做完了才发现某个模块在正式包上不可用返工成本很高。2. 双端发布前必须理清的环境配置2.1 Unity 构建管线与 Player Settings 的取舍Unity 版本我建议直接固定在一个 LTS 版本上不要用太新的 beta 版因为 EasyAR 这类 AR SDK 对新 Unity 版本的适配往往滞后遇到编译报错后很难判断是自己工程的问题还是引擎兼容性问题。确定版本后整个项目期间不要随意升级。Android 构建管线方面Scripting Backend 我选择 IL2CPP虽然编译时间比 Mono 慢但发布包在真机上的稳定性和性能更好。Target Architectures 里只勾 ARM64现在新设备基本都是 64 位系统保留 ARMv7 只会增加包体和兼容负担同时还有可能触发一些老架构下的图形 API 兼容问题。iOS 这边主要是 SDK 版本选择建议选择 Device SDK 而不是 Simulator SDK同时在 Player Settings 里设置一个合理的 Deployment Target目前来看保底设置到 iOS 12 到 13 这个区间可以让设备覆盖范围更广同时也兼容 EasyAR 的运行时要求。2.2 Android 与 iOS 共用参数AR 项目有一个特殊点就是相机的渲染管线直接影响追踪稳定性。Unity 默认的自动图形 API 有时会帮你在 Android 上选到 Vulkan但 EasyAR 在部分设备上对 Vulkan 的适配不如 OpenGLES 3 稳定。我在 Android 的 Player Settings 里把 Graphics API 手动改为 OpenGLES3并取消自动选择录制黑屏和画面撕裂的问题减少了很多。配置项Android 建议值iOS 建议值Scripting BackendIL2CPPIL2CPPTarget ArchitectureARM64ARM64Graphics APIOpenGLES3保持默认MetalMinimum OS Version根据 EasyAR 要求iOS 12 或更高Strip Engine Code可开启可开启还有一点容易被忽略就是垂直同步。AR 相机需要尽可能跟住真实世界的移动如果开了垂直同步画面帧率被锁定在屏幕刷新率有些性能波动时会明显感觉追踪迟滞。我习惯在 AR 场景里关闭垂直同步让相机尽量以最高帧率输出。2.3 权限与隐私申请的优先级移动端 AR 权限集中在三个地方摄像头权限、麦克风权限、相册或存储权限。摄像头是 AR 识别的基础麦克风是录屏录音的基础相册权限用于把录好的视频保存到本地。这三个权限必须在运行时提前申请尤其不要等 EasyAR 初始化已经跑了一半再弹授权框。我踩过一个很典型的坑Android 上先进主菜单再进 AR 场景AR 场景启动时才申请摄像头权限结果 EasyAR 已经提前尝试打开摄像头弹窗回来后相机流是断的画面直接黑屏。后面改成进入 AR 场景之前先在一个纯 UI 页面把摄像头和麦克风权限都拿到再跳转 AR 场景这个问题就没再出现过了。隐私这块也要注意Android 的 manifest 合并有时候会把 EasyAR 示例里的权限带进来如果只做识别不需要麦克风可以在合并后的 manifest 里把麦克风权限移除。iOS 则必须在 Info.plist 里写清楚权限用途描述否则系统会直接终止 App。3. Android 发布实录黑屏、包体与识别素材3.1 摄像头权限的申请时机Android 端最容易复现的故障就是黑屏。AR 场景进入后可以听到声音或者 UI 都能正常显示但画面全黑。这种情况下先不要急着查摄像头硬件先去确认摄像头权限是在什么时候授予的。正确做法是在 AR 相机初始化之前检查权限。如果是在 EasyAR 的 ARSession 已经创建了再授权部分国产 ROM 上相机设备不会被重新打开你需要完全销毁 AR 场景再重建才能恢复。为了稳定我在主菜单页做了一个权限检查入口没有权限时先弹原生授权框用户点允许后点击“进入 AR”按钮这样能确保 AR 场景加载时权限一定就绪。另外从后台回到前台的问题也要单独处理。Android 系统在 App 进入后台一段时间后可能自动断掉相机资源EasyAR 不会像普通播放器那样自动重连。回到前台后我手动判断 ARSession 是否还处于运行状态如果已经中断就把 AR 场景重新加载一次。这个逻辑听起来粗暴但实际测试中是最稳的。3.2 识别图与模型资源的打包策略图片识别的质量跟识别图本身有很大关系。最开始我把一张 2000 像素宽的大海报原图直接做成识别图结果包体变大不说识别速度和稳定性反而不太行。后来发现 EasyAR 这类特征点识别库更在乎图片的纹理丰富度而不是绝对分辨率过度压缩或纯色大面积图片才是最难识别的。我的打包策略统一成这样识别图输出到 1024 像素以内保存为高质量 JPG 或 PNG同时保留原始内容的高对比度结构。这样安装包体积可控识别算法也能更快提取特征点。模型资源方面AR 场景里的模型不要直接用下载的原始高模如果只是放在手机上看面数太高只会增加功耗。我习惯把模型优化到 20 万面以内贴图尽量合并成一张图集材质数量控制在 3 组以内。识别图加载模型后的画面看起来没有差别但录制视频时发热和掉帧会明显改善。另外如果用了 AssetBundle 方式加载模型要注意 Shader 丢失的问题。Bundle 打包时如果没有把 AR 场景用到的 Shader 打进去运行时模型会显示成紫色或直接消失。处理办法是把关键 Shader 添加到 Project Settings 的 Always Included Shaders 列表里保证就算动态加载也不会丢材质。3.3 真机上 AR 画面卡顿的排查思路AR 卡顿不同于普通游戏卡顿AR 一旦掉帧识别框会抖模型像黏在图片上又滑出去观感非常糟糕。开始录屏之后这种情况会更严重因为编码器同时也在抢占 CPU 资源。我排查时先看有没有打开后处理效果比如抗锯齿、动态模糊、泛光这类。AR 场景里这些效果几乎都是多余的不仅看不到明显收益还会让帧率大幅下跌。把后处理关掉后录制状态下的卡顿基本能缓解大半。其次看模型的阴影。实时阴影会要求场景额外渲染一次深度图手机上开销不小。AR 场景中真实光照本来就不固定实时阴影反而容易显得不自然我直接禁掉改用假阴影贴花效果稳定多了。最后是摄像头分辨率。EasyAR 的相机参数可以设置采集分辨率如果设置成最高档录制时经常发热严重。我项目使用的图片识别场景最终把采集分辨率压到 1280x720 档位画面仍清晰但录制帧率稳了很多。4. iOS 发布实录工程导出之后还有不少手工活4.1 Xcode 工程里的必调整项Unity 导出 iOS 工程后直接用 Xcode 打开第一件事不是编译而是把签名设置好。Bundle Identifier 不能用 Unity 默认那一串需要改成自己的应用 ID。团队选择你的开发者证书所在的 Team否则真机会出现签名不够导致的安装失败。然后看 Podfile。Unity 生成的工程里如果包含原生依赖需要先执行一次依赖安装再打开工作空间文件而不是打开原来的工程文件。直接打开工程文件可能会漏掉依赖库编译时冒出各种找不到框架的错误。Bitcode 这个老坑也要注意。Unity 默认在新版本里可能已经不开启 Bitcode 了但如果你的工程从旧版本升级过来一定要去检查。开启 Bitcode 的情况下部分第三方 AR 库会报错或无法通过归档关掉它通常就能解决。导出后如果报链接错误比如找不到某个 C 标准库或 EasyAR 相关的 Undefined Symbol可以在 Build Settings 里的 Other Linker Flags 加上-ObjC这个参数会强制加载静态库里的全部 Objective-C 类很多第三方 SDK 的坑都是这样解决的。4.2 iOS 键盘与后台录制差异iOS 端做录屏要注意一个和 Android 完全不同的行为系统级录屏是整屏捕捉不像 Android 某些方案可以只录应用内画面。这意味着如果录制开始后用户拉出控制中心或者切到其他 App这些界面也会被录进去而 EasyAR 录屏拿到的时间线和系统截取层面并不一致。在实际使用中我尽量避免用户在录制过程中做系统级的页面切换。录制按钮变成“录制中”状态后我会在 UI 上把返回、退出这些按钮隐藏掉防止误触。不是说技术上不能支持切后台而是用户体验上很容易录出奇怪的内容而且隐私上也容易出问题。另外录制过程中如果用户调整音量系统音量提示悬浮层可能会被摄像头录进去。想要完全可控建议录制场景内屏蔽系统音量 HUD 或提前设定好音量不过这个跟 EasyAR 本身无关更像是录屏产品都要处理的细节。4.3 隐私描述与相册权限的坑iOS 打包后最容易崩溃的原因就是 Info.plist 缺少权限描述。常见的三项描述如下权限用途Info.plist 键名说明摄像头NSCameraUsageDescription没有这项启动相机即闪退麦克风NSMicrophoneUsageDescription录屏要录音时必须加添加照片NSPhotoLibraryAddUsageDescription保存录屏到相册时必须加我第一次导 iOS 包时只填了摄像头的描述结果录屏功能一开就闪退日志里明确提示麦克风权限描述缺失。把三项全部补上后就没再出过问题。保存录好的文件也要注意iOS 端写入相册的接口和 Android 不同。EasyAR 录制的文件通常先落在 App 沙盒缓存目录需要手动把视频文件转存到相册。这个转存动作如果没写权限描述会触发系统弹窗失败或直接静默失败。5. easyAR recording 录屏用法与常见问题5.1 录屏的初始化与开始/停止流程EasyAR recording 的核心是一个录屏对象官方文档里通常叫 Recorder 或者 Recorder ControllerUnity 工程里一般挂在一个管理器对象上。用法上其实不复杂但顺序不能乱我按自己项目封装的思路整理成下面这套。先初始化再准备最后开始录制。初始化时要指定输出分辨率、码率、帧率、输出路径和是否采集麦克风。这里如果用文件路径的方式需要保证路径对应的目录已经存在否则可能在准备阶段一直失败。参考调用思路如下只是我项目里的封装习惯EasyAR 4.x 的官方接口名字接近但以你当前版本为准// 初始化录屏配置 recorder.Init(new RecordConfig { width 720, height 1280, bitRate 8 * 1024 * 1024, fps 30, recordMicrophone true, outputPath Application.persistentDataPath /ar_record.mp4 }); // 准备录屏 recorder.Prepare(); // 确认就绪后再开始 if (recorder.IsPrepared) { recorder.Start(); } // 结束录制 recorder.Stop();这个顺序有一个很关键的地方Start 之前必须等待 Prepare 完成不能刚初始化就点开始。部分低端设备 Prepare 需要几百毫秒甚至更久如果使用者在 UI 上连续点击开始按钮容易出现状态竞争录屏文件会损坏。按照同样逻辑Stop 之后也不能立刻再次 Start需要等待录屏对象回到空闲状态。我在 UI 上对录制状态做了互斥保护开始按钮只在空闲时可用停止按钮只在录制中可用避免极端操作触发底层问题。5.2 录屏参数与画质平衡录屏参数不是越高越好这个平衡要结合手机性能和最终用途来定。我给不同场景的建议参数如下使用场景分辨率帧率码率手机短视频分享720x1280306-8 Mbps高清演示或投屏1080x19203010-12 Mbps大量动态画面的演示1080x19206014-16 Mbps为什么要强调分辨率参数要按照 App 的实际屏幕方向来写因为竖屏 App 如果输出横屏的分辨率要么画面被裁切要么四周补黑边。我项目是竖屏所以录屏配置里固定用 720x1280 和 1080x1920实测没有变形。码率方面8 Mbps 在绝大多数平台已经足够清晰除非画面里有大量动态粒子或细密纹理才需要调高到 12Mbps 以上。调太高会带来两个后果一是文件体积暴涨二是编码器实时处理压力大录制时间稍长就开始发热掉帧。帧率 30 就够用。AR 录屏里的模型动作和真实物体都不会有太高速的运动60 帧看起来顺滑但发热和文件体积会显著增加。我最终锁在 30 帧。5.3 录屏后文件找不到、黑屏、没声音这类问题录屏问题里出现频率最高的是文件找不到、黑屏、没声音三类。文件找不到大概率是路径问题有些目录在 Android 上可以写在 iOS 上却不行。我最开始把输出路径直接写到/sdcard/根目录iOS 上直接失败。统一改成应用沙盒目录后Android 和 iOS 都工作正常。文件找到了但黑屏通常跟渲染层级有关。EasyAR 如果使用的是独立相机渲染而录屏模块只捕捉主屏幕画面就可能录出黑屏或空白。解决思路是把 AR 内容渲染到主相机的目标纹理上确保录屏模块能拿到最终合成画面。没声音的问题要分两步排查。先检查录屏配置里有没有开启麦克风采集这一步大部分人都会忘。然后再看系统权限iOS 的麦克风描述有没有填Android 的麦克风权限有没有在录制前被拒绝。权限被拒后不会崩溃只会静默地录到一个无声视频。还有一个隐蔽问题就是录制过程中如果切到后台再回来视频时间轴可能和实际画面不同步。EasyAR 录屏在 iOS 和部分 Android 机型上一旦进入后台就会丢帧或直接停止写入恢复后即使看起来还在录制输出文件也可能长度异常。为防止这种问题我在业务上干脆不允许录制中切后台通过 UI 层限制。6. 排障速查表与一点后期习惯6.1 发布与录制常见问题速查表把前面踩过的问题整理成速查表方便卡住时快速定位。故障现象可能原因解决方向Android 进入 AR 黑屏摄像头权限未提前授予进入 AR 前先申请权限iOS 启动即闪退Info.plist 缺少权限描述补全相机、麦克风、相册描述打包成功后安装失败签名与 Bundle ID 不一致重新设置 Xcode 签名AR 画面卡顿掉帧开启后处理或实时阴影关闭后处理降低模型面数录制文件找不到输出路径无写入权限改为应用沙盒目录录制画面全黑AR 内容未渲染到主屏幕纹理调整相机渲染链录制无声麦克风权限或采集开关未开检查配置和系统权限录制后相册看不到文件未触发媒体库扫描主动刷新媒体库或保存到相册识别图识别率低图片纹理不丰富或过度压缩改用高对比、特征明显的图模型显示为紫色Shader 未打进 Bundle添加 Always Included Shaders这张表不是万能药但覆盖了我从开发到真机测试遇到的大部分问题。如果罗列的现象和你遇到的不完全一样可以对照相近的那一行排查很多问题的根因是重复的。6.2 养成一个先跑最小 Demo 的习惯做 EasyAR 这类跨平台 AR 项目我最想强调的后期习惯是在写业务功能之前先把双平台的最小 Demo 跑通。这个最小 Demo 不需要做任何 UI只要包含摄像机权限申请、EasyAR 初始化、一个简单识别图、一个录制按钮。先在 Android 真机上把 APK 跑通确认能识别、能录制、能保存文件再导 iOS 工程把 Xcode 签名、权限描述、录屏保存流程都验证一遍。双平台都通过后再往里面加业务功能和界面。这样做的好处是后期遇到问题时可以明确区分是 AR 底层问题还是业务代码问题。我见过不少同事把录制黑屏的锅甩给 EasyAR排查到最后发现是自己的后处理相机把画面覆盖了。如果一开始就能对照一个干净的 Demo这类问题十几分钟就能定位。我目前的固定做法是新项目启动的第一周只做底层验证不碰业务界面。等识别和录制两个核心链路在双平台都稳定跑通心里有底了再开始做内容。事实证明这个习惯帮我省下的返工时间远超刚开始那几天看似“浪费”的时间。如果你现在正卡在某个 EasyAR 录屏或者打包的问题上建议你先停下手里的业务代码单独搭一个最小场景把权限、初始化、录制三件事按顺序走一遍大概率能快速定位到问题所在。后面如果有精力也可以把 Android 和 iOS 的录屏文件统一走服务端上传避免用户手机本地存储空间不足导致录制中断这个就是我下一步要扩展的方向了。