简介这份资源面向需要在 Ionic 混合应用中嵌入 Unity 3D 内容的移动端开发者重点解决 Android 与 iOS 双平台上 Unity 与 Ionic 之间的通信问题并可选配合 Vuforia 插件实现 AR 场景。教程已在中等规模的 Unity 商业项目中验证适合具备 Cordova、Objective-C 与 C# 基础的进阶开发者参考。压缩包共 21 个文件约 424KB包含 png 截图、mm 与 m 源文件、java 与 h 头文件、xml 配置、xcconfig 构建配置、json 与 js 脚本以及 cs 脚本等覆盖 iOS 与 Android 两端桥接代码、插件声明与示例页面。目前已有 228 人学习下载。读者可从中获得完整的双端集成骨架、Unity 与 Ionic 互发消息的实现思路、Vuforia 接入的参考配置以及按平台拆分的目录结构便于快速对照搭建自己的混合 AR 应用。1. UnityIonicIntegration 环境搭建从 Unity 3D 到 Ionic 的消息通道把 Unity 3D 场景塞进 Ionic 应用还要让两边互相发消息这事听起来像把两个不同星球的生物关进同一个笼子。我第一次接到这个需求时以为装个 Cordova 插件就完事结果 Android 和 iOS 各炸一次光环境就折腾了两天。UnityIonicIntegration 这套方案解决的就是这个场景Unity 负责 3D 渲染和 AR 逻辑Ionic 负责业务 UI 和页面路由两者通过 Cordova 插件桥接在 Android 和 iOS 上互发消息。它适合正在做 AR 应用、3D 展示类 App 的开发者尤其是已经用 Vuforia 做图像识别的团队。装不好会怎样Unity 画面黑屏、消息发出去收不到、iOS 编译报 Objective-C 链接错误每一个都能让你卡到怀疑人生。下面把我踩过的路按顺序铺开。2. 环境准备Unity、Ionic、Cordova 三件套的版本对齐2.1 版本选择与兼容性对照这套集成对版本敏感不是随便装最新版就能跑。我一般会先把三个核心组件的版本锁死再动手装。Unity 这边建议用 LTS 版本2021.3.x 或 2022.3.x 都行关键是导出 Android 和 iOS 工程时不要选错模块。Ionic 这边CLI 用 7.x底层还是 Cordova 桥接所以 Cordova CLI 要装 12.x 以上。Node.js 用 18 LTS别用 20某些 Cordova 插件在 Node 20 下会报ERR_OSSL_EVP_UNSUPPORTED。组件推荐版本备注Unity2021.3 LTS / 2022.3 LTS需安装 Android Build Support 和 iOS Build SupportIonic CLI7.x全局安装Cordova CLI12.x全局安装Node.js18 LTS避免 Node 20 的 OpenSSL 兼容问题JDK11 或 17Android 编译用Unity 和 Cordova 共用Xcode14.x 以上iOS 编译用需装 Command Line ToolsVuforia 插件如果要用先在 Unity 里导入版本选 10.x它和 Unity 2021.3 LTS 配合最稳。装 Vuforia 之前先把 Unity 关掉导入完再开不然容易卡在包管理器。2.2 安装 Ionic 与 Cordova 命令行工具先装 Node.js 18 LTS装完确认版本node -v # 应输出 v18.x.x npm -v # 应输出 9.x 或 10.x然后全局装 Ionic CLI 和 Cordova CLInpm install -g ionic/cli7 cordova12装完验证ionic -v # 应输出 7.x.x cordova -v # 应输出 12.x.x这里有个坑如果你之前装过旧版 Ionic先npm uninstall -g ionic再装ionic/cli因为旧包名是ionic新包名是ionic/cli两个混在一起会命令冲突。我一般会顺手清一下 npm 缓存npm cache clean --force避免装到一半报校验失败。2.3 创建 Ionic 项目并添加平台新建一个 Ionic 项目模板选 blank 就行ionic start UnityBridge blank --typeangular cd UnityBridge然后添加 Android 和 iOS 平台ionic cordova platform add android ionic cordova platform add ios注意这里必须用ionic cordova而不是ionic capacitor因为 UnityIonicIntegration 是基于 Cordova 插件桥接的Capacitor 不兼容。添加平台时如果卡在Installing platform android多半是网络问题可以配一下 npm 镜像或者手动下载 Cordova 平台包放到缓存目录。我一般会先cordova platform add android --verbose看详细日志确认是下载慢还是 JDK 路径不对。2.4 Unity 导出 Android 与 iOS 工程Unity 这边先建一个 3D 项目把 Vuforia 导入场景里放一个 ARCamera 和 ImageTarget确认能在编辑器里跑通。然后导出AndroidFile → Build Settings → Android → Switch Platform → Export Project勾选 Export Project不要选 Build and RuniOSFile → Build Settings → iOS → Switch Platform → Build导出 Android 工程时Package Name 要和 Ionic 项目的包名一致比如com.example.unitybridge。导出 iOS 工程时Bundle Identifier 也要一致。这两个包名不一致后面消息通道会断因为插件是按包名找 Activity 和 ViewController 的。导出完成后Android 工程是一个 Gradle 项目目录iOS 工程是一个 Xcode 项目目录。这两个目录后面要分别嵌入到 Ionic 的 Cordova 平台里。3. 集成配置把 Unity 工程嵌入 Ionic 并打通消息通道3.1 Android 侧嵌入 Unity 工程与配置 GradleAndroid 侧的集成核心是把 Unity 导出的 Gradle 项目作为模块引入 Ionic 的 Cordova Android 工程。先把 Unity 导出的 Android 工程目录整个拷到 Ionic 项目的platforms/android下改名为unitymodule。然后在platforms/android/settings.gradle里加一行include :unitymodule project(:unitymodule).projectDir new File(unitymodule)接着在platforms/android/app/build.gradle的 dependencies 里加implementation project(:unitymodule)这里有个关键点Unity 导出的build.gradle里 compileSdkVersion 和 targetSdkVersion 可能和 Ionic 工程不一致我一般会把 Unity 模块的这两个值改成和 Ionic 工程一样避免合并 manifest 时冲突。改完执行cd platforms/android ./gradlew clean ./gradlew assembleDebug如果报Duplicate class或Manifest merger failed多半是 AndroidX 和 support 库混用在gradle.properties里加android.useAndroidXtrue android.enableJetifiertrue然后重新 clean 再编译。这一步过了Android 侧的基础集成就算通了。3.2 iOS 侧嵌入 Unity 工程与 Objective-C 桥接iOS 侧比 Android 麻烦因为 Unity 导出的是 Xcode 工程要作为子工程嵌入 Cordova 的 iOS 工程。先把 Unity 导出的 iOS 目录拷到platforms/ios下改名为UnityModule。然后用 Xcode 打开platforms/ios/UnityBridge.xcworkspace把UnityModule/Unity-iPhone.xcodeproj拖进项目导航栏作为子工程。接着配置 Build Settings在 UnityBridge target 的 Build Phases → Link Binary With Libraries 里把 UnityModule 的UnityFramework.framework加进去在 Build Settings → Header Search Paths 里加$(SRCROOT)/UnityModule/Classes和$(SRCROOT)/UnityModule/Libraries在 Build Settings → Other Linker Flags 里加-weak_framework UnityFramework消息通道的桥接文件用 Objective-C 写因为 Unity 的 iOS 接口是 C 的Cordova 插件是 Objective-C 的中间必须用.mm文件做桥。我一般会建一个UnityBridgePlugin.mm里面同时 include Cordova 的CDVPlugin.h和 Unity 的UnityFramework/UnityFramework.h然后实现sendMessageToUnity和onUnityMessage两个方法。编译时如果报Undefined symbol检查UnityFramework.framework是否真的链接进去了有时候拖进子工程后忘了在 Link Binary 里加。3.3 消息通道Cordova 插件注册与双向通信消息通道的核心是一个 Cordova 插件Android 侧用 Java 调 Unity 的UnityPlayer.UnitySendMessageiOS 侧用 Objective-C 调UnityFramework的sendMessageToGOWithName。插件注册在config.xml里plugin nameUnityBridge specUnityBridge param nameANDROID_PACKAGE_NAME valuecom.example.unitybridge / param nameIOS_BUNDLE_ID valuecom.example.unitybridge / /pluginAndroid 侧发消息给 Unity// UnityBridgePlugin.java UnityPlayer.UnitySendMessage(MessageReceiver, OnMessageFromIonic, message);iOS 侧发消息给 Unity// UnityBridgePlugin.mm [[UnityFramework getInstance] sendMessageToGOWithName:MessageReceiver functionName:OnMessageFromIonic message:[message UTF8String]];Unity 侧接收消息的脚本挂在MessageReceiver这个 GameObject 上// MessageReceiver.cs public void OnMessageFromIonic(string message) { Debug.Log(收到 Ionic 消息: message); // 处理消息然后回传 UnityFramework.Instance.SendMessageToIonic(Unity 已收到: message); }回传时Android 用UnityPlayer.currentActivity.runOnUiThread调 Cordova 的webView.sendJavascriptiOS 用UnityFramework的sendMessageToGOWithName回调到插件再转发给 Cordova。这里最容易翻车的是线程问题Unity 的渲染线程和 Cordova 的 UI 线程不是同一个直接跨线程调 UI 会崩。我一般会在插件里加一个 Handler 或 dispatch_async 到主线程再发。4. 避坑排查Android 与 iOS 集成中最容易翻车的 5 个点4.1 现象Android 编译报 Duplicate class原因是 AndroidX 冲突现象./gradlew assembleDebug时报Duplicate class android.support.v4.app.Fragment和androidx.fragment.app.Fragment同时存在。原因Unity 导出的 Android 工程默认用旧版 support 库而 Ionic 的 Cordova 工程已经迁到 AndroidX两者混用导致类重复。解决在platforms/android/gradle.properties里加android.useAndroidXtrue和android.enableJetifiertrue然后./gradlew clean再编译。如果还报检查 Unity 模块的build.gradle里有没有implementation com.android.support:appcompat-v7:xx有就删掉换成 AndroidX 对应包。4.2 现象iOS 编译报 Undefined symbol原因是 UnityFramework 没链接现象Xcode 编译时报Undefined symbol: _UnityFrameworkGetInstance或_sendMessageToGOWithName。原因UnityModule 作为子工程拖进来了但 UnityFramework.framework 没有加到 Link Binary With Libraries 里或者 Header Search Paths 没配。解决在 UnityBridge target 的 Build Phases → Link Binary With Libraries 里手动加UnityFramework.framework路径指向UnityModule/UnityFramework.framework。然后在 Build Settings → Header Search Paths 里加$(SRCROOT)/UnityModule/Classes和$(SRCROOT)/UnityModule/Libraries。改完 Clean Build Folder 再编译。4.3 现象消息发出去收不到原因是 GameObject 名字对不上现象Ionic 调sendMessageToUnity后Unity 侧没有任何日志消息像石沉大海。原因UnitySendMessage的第一个参数是 GameObject 名字必须和 Unity 场景里挂脚本的 GameObject 名字完全一致包括大小写。我见过有人场景里叫MessageReceiver代码里写messageReceiver结果死活收不到。解决在 Unity 场景里确认挂MessageReceiver.cs的 GameObject 名字然后插件里UnitySendMessage的第一个参数严格一致。Android 和 iOS 两边都要检查因为两个平台是分开写的。4.4 现象iOS 上 Unity 画面黑屏原因是 Metal 与 OpenGL 冲突现象iOS 真机上 Ionic 页面正常但 Unity 视图区域全黑日志里没有明显报错。原因Unity 导出 iOS 时默认用 Metal 渲染而 Cordova 的 WebView 可能占用 OpenGL 上下文两者冲突导致 Unity 渲染失败。解决在 Unity 的 Player Settings → iOS → Graphics APIs 里把 Metal 去掉只留 OpenGL ES 3.0。或者反过来在 Cordova 的config.xml里加preference nameUseWebViewEngine valueWKWebView /让 WebView 用 WKWebView 而不是 UIWebView减少图形上下文冲突。我一般两个都改稳一点。4.5 现象Android 上消息回传崩溃原因是线程不对现象Unity 调SendMessageToIonic后Android 应用直接闪退日志里报CalledFromWrongThreadException。原因Unity 的SendMessageToIonic是在 Unity 渲染线程里调的而 Cordova 的webView.sendJavascript必须在 UI 线程调跨线程直接崩。解决在 Android 插件的SendMessageToIonic方法里用activity.runOnUiThread包一层activity.runOnUiThread(new Runnable() { Override public void run() { webView.sendJavascript(javascript:onUnityMessage( message )); } });iOS 侧同理用dispatch_async(dispatch_get_main_queue(), ^{ ... })包一层。这个坑我踩过两次第一次不知道原因第二次看到CalledFromWrongThreadException才反应过来。5. 验证跑通从 Ionic 发消息到 Unity 再回传的完整链路检查装完不算完得验证消息通道真的通了。我一般会按「Ionic → Unity → Ionic」的顺序走一遍每一步都打日志确认链路没有断点。先在 Ionic 页面里加一个按钮点击时调插件发消息// home.page.ts declare var cordova: any; sendToUnity() { cordova.plugins.UnityBridge.sendMessageToUnity( Hello from Ionic, () console.log(发送成功), (err: any) console.error(发送失败, err) ); }然后在 Unity 的MessageReceiver.cs里加日志public void OnMessageFromIonic(string message) { Debug.Log(Unity 收到: message); UnityFramework.Instance.SendMessageToIonic(Echo: message); }最后在 Ionic 侧监听回传// home.page.ts ngAfterViewInit() { document.addEventListener(unityMessage, (event: any) { console.log(Ionic 收到回传: , event.detail); }); }验证时按这个顺序检查检查点预期结果失败时看什么Ionic 调 sendMessageToUnity控制台输出「发送成功」插件是否注册config.xml 里有没有 UnityBridgeUnity 收到消息Unity 控制台输出「Unity 收到: Hello from Ionic」GameObject 名字是否一致UnitySendMessage 参数对不对Unity 回传Unity 控制台输出「Echo: Hello from Ionic」SendMessageToIonic 是否被调线程是否在主线程Ionic 收到回传浏览器控制台输出「Ionic 收到回传: Echo: Hello from Ionic」webView.sendJavascript 是否执行事件监听是否注册Android 上用adb logcat | grep Unity看 Unity 日志iOS 上用 Xcode 控制台看。如果某一步断了就回到对应章节检查配置。我一般会在每个环节加console.log或Debug.Log确保消息每经过一个节点都有记录这样断在哪一目了然。还有一个技巧如果 Android 上 Unity 画面显示但消息不通先检查UnityPlayer.UnitySendMessage的 GameObject 名字再检查 Unity 场景是否真的加载了MessageReceiver脚本。iOS 上如果消息通了但画面黑检查 Metal 和 OpenGL 的设置。这两个平台的问题经常是反着来的Android 画面容易通但消息容易断iOS 消息容易通但画面容易黑。从那以后我每次集成 Unity 和 Ionic都强制走一遍「发消息 → 收消息 → 回传 → 收回传」的完整链路不看到四个日志全打出来不算完。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?