整合目的
Ionic是基于前端技术开发移动端应用的框架,Unity可以开发跨平台3D场景应用的框架。两者结合可以实现轻量型移动端三维应用的快速开发。本文的目的是将Ionic前端项目(页面,大型三维场景)与Unity ARKit项目(设备相机交互,小场景)结合。
框架版本
本文使用的Ionic、Cordova、Unity和Xcode版本如下:
ionic (Ionic CLI) : 3.9.2
Cordova CLI : 8.0.0
Node : v8.9.3
npm : 5.5.1
OS : Windows 10
运行在VMWare 14 pro虚拟机上的macOS High Sierra 10.13.6 (17G65)
Unity 2018.2.0f2 (64-bit)
Xcode 9.4.1 (9F2000)
本文通过以上配置成功实现了Ionic和Unity3D的整合与通讯,但是以上配置不是唯一的,其他配置请自行验证。
使用的插件
本文使用的是Github上的UnityIonicIntegration代码仓库,以下简称repo。
Ionic配置
1. 添加插件
在创建的Ionic项目的命令行中输入ionic cordova plugin add https://github.com/yasirkula/UnityIonicIntegration.git
。安装完成后,在package.json和config.xml中会有unity字样的cordova插件存在,不同的ionic版本可能会有安装失败的情况(如3.10.x以上的版本会安装失败)。
2. 编写调用Unity窗口的代码
import ...
// 需要在@Component之前声明unityARCaller
declare let unityARCaller: any;
@Component({
...
})
export class ...
{
constructor() {
...
}
openUnity() {
// 可以在开启Unity窗口时传入一个字符串(选填)
unityARCaller.launchAR( "my message for Unity-side", this.uReturnedFromUnity, this.uMessageReceivedFromUnity );
}
sendMessageToUnity() {
// 在Unity运行时传入字符串
unityARCaller.sendMessage( "Function name", "Optional parameter" );
}
uReturnedFromUnity = (param) => {
// param:String is the (optional) message returned from Unity-side
alert( param );
};
uMessageReceivedFromUnity = (message) => {
// message:从Unity端获取的字符串
console.log( "=========" + message + "=========" );
};
}
3. 编译Ionic项目
在项目命令行中输入ionic cordova platform add ios
和ionic build ios
.
Unity配置
导入脚本
在Unity项目中导入repo/files中的IonicComms.cs脚本。可以绑定到一个GameObject上,也可以不绑定。
如果Ionic中调用launchAR
时传入了一个字符串给Unity,可以在IonicComms.cs的OnMessageReceivedFromIonic
方法下对传入的message进行使用和处理。若要从Unity返回Ionic,可以在Unity中调用IonicComms.FinishActivity()
方法,同样可以在参数中向Ionic传回一个字符串。
针对iOS项目,还需要将repo/files中的uIonicComms.mm文件放入Unity项目的Assets/Plugins/iOS目录下(如果没有该目录,请自行创建)。
编译配置
针对iOS项目,需要在Player Settings->Other Settings->Configuration中将Scripting Backend设置为IL2CPP。 针对ARKit项目,需要在Player Settings->Other Settings->Configuration中勾选Requires ARKit support(Target SDK设置为11,因为只有iOS 11支持ARKit)
编译
以上配置完成后,将该Unity项目变异成iOS项目,放在空文件夹中。
iOS配置
因为iOS配置较为繁琐,需要使用macOS和Xcode进行开发,步骤如下:
在macOS中用Xcode打开之前编译好的Ionic项目(注意:要打开.wcworkspace文件而不是.xcodeproj文件)
在项目的Plugins/unityARCaller.m文件中,将(void)launchAR和(void)sendMessage函数内的注释去掉。
将Classes/AppDelegate.m和Other Sources/main.m的后缀名从.m改为.mm
将Classes/AppDelegate.h文件中的内容替换成repo/files中的AppDelegate.h
将Classes/AppDelegate.mm文件中的内容替换成repo/files中的AppDelegate.mm
下面我们要将Unity编译的项目导入到Xcode项目中
在项目中创建一个新的组(Group),命名为Unity
将Unity编译项目中的Classes和Libraries文件夹拖入Unity组中,选择Create groups,不选Copy items if needed
将repo/files中的unityconfig.xcconfig文件拖入Unity组中,选择Create groups,不选Copy items if needed
将Unity编译项目中的Data文件夹拖入Unity组中,选择Create folder references,不选Copy items if needed
移除Unity组中Libraries/libil2cpp文件夹,选择Remove References
如果Unity组中存在Libraries/Plugins/Android文件夹,则移除,选择Remove References
在项目的Configuration中设置所有的配置使用unityconfig
在Build Settings中,将UNITYIOSEXPORTED_PATH设置为编译好的Unity iOS项目文件夹(注意:PROJECT和TARGETS都要设置)
在Build Settings中,点选Prefix Header栏目,点击Delete按键,设置为默认值(注意:默认情况下,该栏目已经设置了默认值,无需修改。PROJECT和TARGETS都要设置)
打开Unity组中的Classes/UnityAppController.h,找到以下代码:
inline UnityAppController* GetAppController()
{
return (UnityAppController*)[UIApplication sharedApplication].delegate;
}
替换成
NS_INLINE UnityAppController* GetAppController()
{
NSObject<UIApplicationDelegate>* delegate = [UIApplication sharedApplication].delegate;
UnityAppController* currentUnityController = (UnityAppController *)[delegate valueForKey:@"unityController"];
return currentUnityController;
}
- 打开Unity组中的Classes/UnityAppController.mm,找到
- (void)shouldAttachRenderDelegate {}
,替换成以下代码:
- (void)shouldAttachRenderDelegate {
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[delegate shouldAttachRenderDelegate];
}
在Unity组中的Classes/UnityAppController.mm顶部添加
#import "AppDelegate.h"
将Other Sources/main.mm中的内容替换成Classes/main.mm(Unity组中)的代码,然后在Other Sources/main.mm中找到
const char* AppControllerClassName = "UnityAppController"
替换成const char* AppControllerClassName = "AppDelegate"
在Unity组中的Classes/main.mm移除,选择Remove References
在Build Settings中,追加
-DRUNTIME_IL2CPP=1
到Other C Flags和Other C++ Flags中(PROJECT和TARGETS都要设置)在TARGETS的配置中的Link Binary With Libraries中添加ARKit.framework
在Resources/项目名-info.plist中,添加Privacy - Camera Usage Description,输入任意字符串的值就可以了
最后将整个项目进行编译(需要编译到真实的设备中,不能使用模拟器,否则会报错)
注意事项:如果使用的是虚拟机macOS,需要将所有编译相关的文件都复制到macOS自己的磁盘上,不能使用共享的Windows文件夹。