最近游戏组让配合开发一个 “在Unity中点击按钮弹出原生二维码扫码页面 -> 再把获取到的二维码信息传回给Unity” 的功能,于是我就开始了学习iOS与Unity3d交互的不归路~。
由于对Unity不熟,导出的Xcode工程跟平时用的Xcode也有些差异,遇到了很多没遇到过的问题,只能慢慢摸索,慢慢解决。
刚开始在网上下载下来的Xcode Demo无法在真机上运行(在模拟器上正常)、添加不了Pod,只好自己新建一个干净的Unity工程,仿照Unity Demo编写交互代码再重新导出Xcode工程,没有问题了再对接二维码扫码的功能。
一、代码实现:
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要建立好绑定关系,不然无效.
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]
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
b、选择iOS,第一次装的时候需要先下载一个iOS支持文件,下载完成后安装。
重启unity->Build(release)
这样就创建成功一个苹果工程了
选择iOS后要点击Switch Platform,不然打不了iOS包
点击player settings->Target SDK可以选择映射出来的苹果项目是运行于模拟器的还是真机的。
2、打包上架遇坑:
在给游戏打苹果包的时候,发现在最后一步一直显示Compiling bitcode超时
原因:
Enable Bitcode设置的YES,工程进行了Bitcode编译很耗时。我查看了其他工程都是设置的NO
解决:
Build Settings->Enable Bitcode设置为NO
3、探索:(待完善)
游戏端的代码更新了,可不可以做到直接在原有的Xcode工程上替换unity相关文件,而不需要每次都重新生成Xcode工程,再在新工程上重新写一遍IOS代码;
如果必须每次都写一遍的话,那就把代码封装到工具类中,每次只需要拖入工具并改少量的代码就行。把iOS代码复用性做到最高,耦合性降到最低。
扫码相关的内容就不细说了,可以下载我的代码 MyUnityToIOS了解 提取码:feeg。里面有Unity和Xcode两端的代码,感兴趣的可以自己下载下来慢慢看~.~
资料