Ionic与Unity3D ARKit项目的整合与通讯

整合目的

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 iosionic 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.mOther Sources/main.m的后缀名从.m改为.mm

  • Classes/AppDelegate.h文件中的内容替换成repo/files中的AppDelegate.h

  • Classes/AppDelegate.mm文件中的内容替换成repo/files中的AppDelegate.mm

下面我们要将Unity编译的项目导入到Xcode项目中

  • 在项目中创建一个新的组(Group),命名为Unity

  • 将Unity编译项目中的ClassesLibraries文件夹拖入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=1Other C FlagsOther C++ Flags中(PROJECT和TARGETS都要设置)

  • TARGETS的配置中的Link Binary With Libraries中添加ARKit.framework

  • Resources/项目名-info.plist中,添加Privacy - Camera Usage Description,输入任意字符串的值就可以了

  • 最后将整个项目进行编译(需要编译到真实的设备中,不能使用模拟器,否则会报错)

注意事项:如果使用的是虚拟机macOS,需要将所有编译相关的文件都复制到macOS自己的磁盘上,不能使用共享的Windows文件夹。

浙ICP备16041529号-1