iOS与Unity3D交互

最近游戏组让配合开发一个 “在Unity中点击按钮弹出原生二维码扫码页面 -> 再把获取到的二维码信息传回给Unity” 的功能,于是我就开始了学习iOS与Unity3d交互的不归路~。

由于对Unity不熟,导出的Xcode工程跟平时用的Xcode也有些差异,遇到了很多没遇到过的问题,只能慢慢摸索,慢慢解决。

刚开始在网上下载下来的Xcode Demo无法在真机上运行(在模拟器上正常)、添加不了Pod,只好自己新建一个干净的Unity工程,仿照Unity Demo编写交互代码再重新导出Xcode工程,没有问题了再对接二维码扫码的功能。

iOS与Unity3D交互_第1张图片

一、代码实现:


1、Unity代码:

添加一个C#文件,添加实现代码。

// Unity代码

using UnityEngine;

using System.Collections;

using System.Runtime.InteropServices;

public class Test : MonoBehaviour {

    public GameObject cube;

    // DllImport这个方法相当于是告诉Unity,有一个unityToIOS函数在外部会实现。

    // 使用这个方法必须要导入System.Runtime.InteropServices;

    [DllImport("__Internal")]

    private static extern void unityToIOS ( string str );

    public string scanStatus;//二维码扫描结果

    void OnGUI(){

         // 当点击按钮后,调用外部方法

         if (GUI.Button (new Rect (100, 100, 200, 60), "跳转IOS")) {

             // Unity调用ios函数,同时传递数据

             unityToIOS ("Hello IOS");

         }

        //控件要写在GUI里面 可以设置一个全局str,赋值,OnGUI是每秒都会自动刷新。

       GUI.Label (new Rect (100, 200, 400, 60), scanStatus); 

    }

    // 用户取消了扫码

    void cancelScan(string str){

         scanStatus = str;

    }

    // 获取二维码成功

    void getQRSuccess(string str){

         scanStatus = @"二维码内容:" + str;

    }

    // 向右转函数接口

    void turnRight(string num){

         float f;

         if (float.TryParse (num, out f)) {// 将string转换为float,数据之间的传递只能以string类型

             Vector3 r = new Vector3 (cube.transform.rotation.x, cube.transform.rotation.y - 10f, cube.transform.rotation.z);

             cube.transform.Rotate (r);

         } 

}}


2、iOS代码:

iOS端主要在UnityAppController.mm文件中编写代码 (创建一个LARManager.h文件并创建一些交互方法)。

// MARK: - 直接加载unity页面

- (void)startUnity:(UIApplication*)application{

    //新增代码

    [self showUnityPage];

    /* 隐藏了一些Unity代码 */

}

// MARK: - 展示Unity页面

- (void)showUnityPage {

    if ([LARManager sharedInstance].unityIsPaused) {

        UnityPause(false);//打开Unity

        [LARManager sharedInstance].unityIsPaused = NO;

        //设置rootView为Unity界面

        self.window.rootViewController = self.rootViewController;

 }}


iOS调用Unity:通过UnitySendMessage方法实现。

UnitySendMessage("gameobject", "Method", msg);

参数一为unity脚本挂载的gameobject

参数二为unity脚本中要调用的方法名

参数三为传递的数据,*注意:传递的数据只能是char 类型

// MARK: - iOS传递事件给Unity ScanDelegate

//取消扫描

- (void)cancelScan {

    [self showUnityPage];

    UnitySendMessage("Main Camera", "cancelScan", [@"取消扫描" UTF8String]);

}

//获取二维码信息成功

- (void)getQRSuccess:(NSString *)str{

    [self showUnityPage];

    UnitySendMessage("Main Camera", "getQRSuccess", [str UTF8String]);

}

- (void)turnRight{//右转

    const char* str = [[NSString stringWithFormat:@"10"] UTF8String];

    UnitySendMessage("Main Camera", "turnRight", str);//IOS调用Unity的方法,通过UnitySendMessage方法实现。

}

- (void)turnLeft{//左转

    const char* str = [[NSString stringWithFormat:@"10"] UTF8String];

    UnitySendMessage("Main Camera", "turnLeft", str);

}


Unity调用iOS:实现Unity的调用方法

// MARK: - Unity传递事件给iOS (跳转到iOS界面,Unity界面暂停)

extern "C"{

    void unityToIOS(char* str){// 对Unity中的unityToIOS方法进行实现

        NSLog(@"*************%s",str);// Unity传递过来的参数

        UnityPause(true);//暂停Unity

        [LARManager sharedInstance].unityIsPaused = YES;


        //扫码页面

        ScanController *vc = [ScanController new];

        vc.delegate = GetAppController().self;//添加代理

        GetAppController().scanVC = vc;

        // GetAppController()获取appController,相当于self; UnityGetGLView()获取UnityView,相当于_window; 点击按钮后跳转到IOS界面,设置界面为IOS界面

        GetAppController().window.rootViewController = GetAppController().scanVC;

}}

二、遇到的问题:


1、在Unity中: C#脚本Test和控件Cube要建立好绑定关系,不然无效.

iOS与Unity3D交互_第2张图片

2、(巨坑:浪费了我不少时间~.~)

Xcode:打包出来没有在IOS中实现Unity定义的交互函数,运行Xcode就报错,还以为是在网上下载的demo代码有问题。

原因:

没有实现Unity定义的交互函数_unityToIOS

解决:

在 extern "C”{中实现相关函数

3、把IOS代码拖入工程后运行__weak typeof(self) wSelf = self声明报错:

a parameter list without types is only allowed in a function definition。

原因:

可能是编译器识别不了typeof关键字

解决:

Apple LLVM 6.1 - Language设置C Language Dialect为Compiler Default或者GNU99[-std=gnu99]

iOS与Unity3D交互_第3张图片

4、继续报错

Undefined symbols for architecture arm64: "_kCGImagePropertyExifDictionary", referenced from: -[SGQRCodeObtain captureOutput:didOutputSampleBuffer:fromConnection:] in SGQRCodeObtain.o

原因:

引用第三方库时是直接把代码拖进工程的,可能漏了某些文件.

解决:

直接用pod导入第三方库.

5、用到了相机、相册或其他功能忘记添加访问权限配置,导致闪退

解决:

要在info.plist中添加访问权限配置


三、拓展:


1、Unity导出Xcode工程:

下载好Unity项目并打开 -> File -> Building Setting -> iOS-> Switch Platform -> Add Open Scenes -> Player Setting -> .NET 2.0 -> Build

a、首先在File->Build Settings

iOS与Unity3D交互_第4张图片

b、选择iOS,第一次装的时候需要先下载一个iOS支持文件,下载完成后安装。

重启unity->Build(release)

这样就创建成功一个苹果工程了

选择iOS后要点击Switch Platform,不然打不了iOS包

iOS与Unity3D交互_第5张图片

点击player settings->Target SDK可以选择映射出来的苹果项目是运行于模拟器的还是真机的。

iOS与Unity3D交互_第6张图片

2、打包上架遇坑:

在给游戏打苹果包的时候,发现在最后一步一直显示Compiling bitcode超时

iOS与Unity3D交互_第7张图片

原因:

Enable Bitcode设置的YES,工程进行了Bitcode编译很耗时。我查看了其他工程都是设置的NO

解决:

Build Settings->Enable Bitcode设置为NO


3、探索:(待完善)

游戏端的代码更新了,可不可以做到直接在原有的Xcode工程上替换unity相关文件,而不需要每次都重新生成Xcode工程,再在新工程上重新写一遍IOS代码;

如果必须每次都写一遍的话,那就把代码封装到工具类中,每次只需要拖入工具并改少量的代码就行。把iOS代码复用性做到最高,耦合性降到最低。

扫码相关的内容就不细说了,可以下载我的代码 MyUnityToIOS了解 提取码:feeg。里面有Unity和Xcode两端的代码,感兴趣的可以自己下载下来慢慢看~.~

资料

iOS与Unity3d交互

Unity里调用iOS原生

Unity3D与iOS的交互

swift-unity

你可能感兴趣的:(iOS与Unity3D交互)