在上一篇文章中,已经将unity框架嵌入到我们的xcode项目中了传送门
接下来,就要在项目中跑起来Unity里面的东西了。其实,如果交互不多的话,我们需要做的东西很少,基本上Unity已经全部做好了,但是安装包会增大很多,如果长期嵌入的话,需要再对安装包做一下处理,让安装包小一些。
正题(添加Unity的代码):
-
在AppDelegate.h里添加
// Unity文件 #import "UnityAppController.h" //----------------- 以下参数仅仅用于Unity -----------------// /// Unity 的 AppDelegate @property (strong, nonatomic) UnityAppController *unityController; /// Unity 显示视图 @property (strong, nonatomic) UIWindow *unityWindow; - (void)showUnityWindow; - (void)hideUnityWindow; //----------------- 以上参数仅仅用于Unity -----------------//
-
在AppDelegate.m里添加
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { { // Unity _unityController = [[UnityAppController alloc] init]; [_unityController application:application didFinishLaunchingWithOptions:launchOptions]; } } //程序进入前台并处于活动状态时调用 - (void)applicationDidBecomeActive:(UIApplication *)application { [self.unityController applicationDidBecomeActive:application]; } // APP从后台进入前台 - (void)applicationWillEnterForeground:(UIApplication *)application{ [self.unityController applicationWillEnterForeground:application]; } /** APP从前台进入后台 */ -(void)applicationDidEnterBackground:(UIApplication *)application { [self.unityController applicationDidEnterBackground:application]; } #pragma mark 应用终止 -(void)applicationWillTerminate:(UIApplication *)application { [self.unityController applicationWillTerminate:application]; } #pragma mark =================== Unity =================== -(void)applicationWillResignActive:(UIApplication *)application { [_unityController applicationWillResignActive:application]; } /// 显示AR页面 -(void)showUnityWindow{ [self.unityWindow makeKeyAndVisible]; } -(void)hideUnityWindow{ [self.window makeKeyAndVisible]; } -(UIWindow *)unityWindow{ return UnityGetMainWindow(); }
-
调用方法,进入和退出Unity Windows
-(void)go { //进入unity界面 [(AppDelegate *)[UIApplication sharedApplication].delegate showUnityWindow]; UnityPause(false); } - (void)quit{ //退出unity界面 UnityPause(true); [(AppDelegate *)[UIApplication sharedApplication].delegate hideUnityWindow]; }
Unity调用iOS方法
RegisterMonoModules.h 文件里填写相应的方法
void getLevelAndCoin();
-
如果需要调用传递返回值的方法,也需要写成void类型 RegisterMonoModules.mm 不需要写对一个的方法
-
UnityAppController.mm里边填写对应的方法实现
extern "C"
{
const char* getLevelAndCoin(){
// do something
return strdup([@"Test" UTF8String]);
}
}
返回类型要通过strdup封装一下,直接return “Test” 会运行时崩溃
iOS调用Unity方法
iOS调用Unity方法,比较简单,直接让他们提供相应的方法即可
如果通过Swift调用,需要在桥接文件里导入一下#import <Classes/Unity/UnityInterface.h>
接入Unity后,SSZipArchive会在解压时崩溃
现象是会在解压时,这个方法会报内存错误:
unzOpenCurrentFile
Thread 39: EXC_BAD_ACCESS (code=1, address=0x1177140)
找了一些资料,和很多种解决办法,都无法解决,原因应该和负责Unity同事的说法差不多
因为引入的多个库中都有结构体
unz_file_info
,但是他们的定义不一样(一个库是ZipArchive一个是Zip,还有是引入的.a中也存在这个结构体,我们在继续看为啥没报符号表冲突的问题)。在实际运行的时候,变量directoriesModificationDates被污染了。找了一下原因,是因为实际使用的unz_file_info的定义不是ZipArchive库中的,而是其他的。在Runtime时unz_file_info与ZipArchive中的定义的内部布局不一致。于是污染了堆栈,于是directoriesModificationDates指针就意外的被换成了脏数据。这也就是为什么,在调用之前加了一个没有啥用的fileInfoFake,就能正常使用的原因。 fileInfoFake所在的内部被污染了,防止了其他变量被污染。 造成这个问题的原因,是库冲突导致的。看了一下Zip、ZipArchive都直接源码引用了minizip的代码。为了避免这种冲突的问题,还是建议要么直接把minizip抽成一个库。要么重命名一下使用到的minizip符号。避免这种隐藏极深的问题。
我将ZipArchive封装成一个framework或者.a的静态库都会造成崩
最后不得不换了一个解压框架 ——_——
ZipZap