在上一篇文章中,已经将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
如果有人知道这个框架冲突的问题怎么解决,劳烦解惑一下