iOS项目集成unity工程

unity版本 2017.1.1f1 Xcode版本8.2.1 (8C1002)


第一步

导出unity的Xcode工程(具体导出设置可以看文章末尾的链接大多数都有讲到设置) 此时需要注意的是

  • Bundle ID 要与你iOS项目保持一致(一定要一致否者可能会报很多莫名其妙的错误)

第二步

将导出的unity工程中的以下四个文件导入到你的项目中 (如果是旧版unity可能还有一个MapFileParser文件)

unity文件.png

注意 千万不要选错导入方式

  • Data一定要是这样选择导入(导入完成后Data是蓝色的文件夹)


    导入Data.png
  • 另外三个选择Creat Groups

第三步

  • 照着unity导出的项目中TARGETS ->Build Phases->Link Binary With Libraries的依赖库
    在你自己的iOS原生项目中挨个添加依赖库(已经有了的就不用管它 千万不要重复 也不要漏)
  • 如果有需要 在Build Phases中搜索.mm文件 在有需要的.mm文件上打上-fno-objc-arc(MRC标签);
  • 然后添加脚本路径

    这里需要注意一下写成"$PROJECT_DIR/Smart_ticket_iOS/MapFileParser.sh"也是可以的 并且应该以导入项目时的路径为准不是照着这个写(具体思路见下面设置头文件路径)

第四步

工程配置

  1. 关闭bitcode。(已经关闭的可以忽略)新版的Unity已经支持Bitcode但你unity项目中的某些SDK可能并不支持,不关闭无法正常编译。
  2. 添加 Build SettingsHeader Search PathsLibrary Search Paths
  • 需要特别强调一下 这里有个坑 这里的路径是你自己第二步中导入的四个文件的路径,你导入的路径是什么这里就写什么 不是照着我的写 比如文件路径是下面这样的
    文件路径.jpg

    那么Header Search Paths就应该添加
$(SRCROOT)/Smart_ticket_iOS/Classes
$(SRCROOT)/Smart_ticket_iOS/Classes/Native
$(SRCROOT)/Smart_ticket_iOS/Libraries/libil2cpp/include
$(SRCROOT)/Smart_ticket_iOS/Libraries
$(SRCROOT)/Smart_ticket_iOS

Library Search Paths应该添加

$(PROJECT_DIR)/Smart_ticket_iOS/Libraries
$(PROJECT_DIR)/Smart_ticket_iOS/Libraries/Plugins/iOS
$(PROJECT_DIR)/Smart_ticket_iOS/

如果unity的文件放在项目根目录 那就应该添加

$(SRCROOT)/Classes
$(SRCROOT)/Classes/Native
$(SRCROOT)/Libraries/libil2cpp/include
$(SRCROOT)/Libraries
$(SRCROOT)
$(PROJECT_DIR)/Libraries
$(PROJECT_DIR)/Libraries/Plugins/iOS
$(PROJECT_DIR)
  • 一般来说Library Search Paths不需要特别设置 你导入文件的时候Xcode就会自动帮你设置好
    但是如果这个设置不对会出现library not found for -liPhone-lib之类的错
  • Header Search Paths如果设置不对会出现
    'codegen/il2cpp-codegen.h' file not found等一系列错误
  1. Build Settings->Other C Flags添加-DINIT_SCRIPTING_BACKEND=1 如果无效可以尝试把这个值移到最上面
  • 如果在最后编译成功了 但是运行后却在执行unity代码时日志打印was compiled with optimization - stepping may behave oddly; variables may not be available(其实这只是个警告并不是崩溃原因,这个警告是由于unity生成libiPhone-lib.a时使用了编译优化引起的)并崩溃可以尝试添加-DRUNTIME_IL2CPP=1我的项目就是这样 估计是因为添加了AR 添加了以后就可以正常运行了
  1. 添加自定义设置
UNITY_RUNTIME_VERSION -> xxx(你导出的unity项目中对应的版本号)
UNITY_SCRIPTING_BACKEND -> il2cpp

  • 我的项目只添加了上面两项就运行成功了 但是其他文档中有些提及到还要添加
MTL_ENABLE_DEBUG_INFO -> NO (这个是本来就有的修改就行)
GCC_THUMB_SUPPORT NO 
GCC_USE_INDIRECT_FUNCTION_CALLS NO 
  1. 将iOS原生项目中的pch文件合并到Classes/Prefix.pch中,并且在Build Settings->Prefix Header中设置路径(如果没有就不做合并但是仍然要设置unity项目的pch路径)
  • 合并的时候需要注意 你原本项目中pch的内容一定要放在如下部分


否则放外面的话会报unknown type name 'NSString'之类的错

  1. 复制unity项目文件夹Classes中的main.mm文件中的代码(所有),删除你原生项目的main.m中的代码(除了最开始的头文件引用部分),将复制的内容粘贴到原生项目的main.m中,删除main.mm,修改main.m为main.mm(此时如果编译成功运行的时候进入的是unity页面 没有走我们原生的AppDelegate)
  • 注意编译请选择真机 集成unity后不支持模拟器
  • 如果你忘记删除main.mm会报冲突说你有两个main
  • 如果你忘记修改main.m为main.mm会报'csignal' file not found等错
  1. 修改启动函数(从我们自己的AppDelegate启动)在修改后的main.mm中
找到
UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
将之修改为
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

此时再启动的话就是走我们原来的AppDelegate了

  1. 添加跳转unity页面的功能
    修改Appdelegate.h为如下样式
#import <UIKit/UIKit.h>
#import "UnityAppController.h"
@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) UIWindow *unityWindow;

@property (strong, nonatomic) UnityAppController *unityController;

- (void)showUnityWindow;
- (void)hideUnityWindow;
@end

Appdelegate.m中添加或修改

- (UIWindow *)unityWindow{
    
    return UnityGetMainWindow();
    
}

- (void)showUnityWindow{
    
    if (_isFirstShowUnity) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(15, 25, 20, 40);
        [btn setImage:[UIImage imageNamed:@"返回"] forState:UIControlStateNormal];
        [btn addTarget:self action:@selector(hideUnityWindow) forControlEvents:UIControlEventTouchUpInside];
        [self.unityWindow addSubview:btn];
        _isFirstShowUnity = NO;
    }
    
    [[UIApplication sharedApplication] setStatusBarHidden:YES];
    
   UnityPause(0);
    
    [self.unityWindow makeKeyAndVisible];
    
}

- (void)hideUnityWindow{
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
    
    UnityPause(1);
    
    [self.window makeKeyAndVisible];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    在你的原有基础上 return YES 之前 添加
    self.unityController = [[UnityAppController alloc] init];
    [self.unityController application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)applicationWillResignActive:(UIApplication *)application {
    [self.unityController applicationWillResignActive:application];
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    [self.unityController applicationDidEnterBackground:application];
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    [self.unityController applicationWillEnterForeground:application];
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    [self.unityController applicationDidBecomeActive:application];
}


- (void)applicationWillTerminate:(UIApplication *)application {
    [self.unityController applicationWillTerminate:application];
}

在导入的unity文件夹Classes/UnityAPPController.h中找到

记得 #import "AppDelegate.h"
inline UnityAppController*  GetAppController()
{
//    return (UnityAppController*)[UIApplication sharedApplication].delegate;原有的 注释掉
    AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    return delegate.unityController;
---------如果上面的报错 换下面的写法
    return (UnityAppController*)[[UIApplication sharedApplication] valueForKeyPath:@"delegate.unityController"];
}

然后在需要调用unity的地方调用方法切换成unity页面

AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[delegate showUnityWindow];

遇到的坑

  • 如果编译报很多类似
Undefined symbols for architecture arm64:
  "_glStateCacheTexEnvCombine", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheTexEnvSrc1", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheEnableTex2D", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheEnableClientStateTexCoordArray", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheTexEnvMode", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheDisableTex2D", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheEnableClientStateVertexArray", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheClientActiveTexture", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheDisableDepthTest", referenced from:
      _arglDispImage in libHiARWrapper.a(gsub_es.o)
  "_glStateCachePixelStoreUnpackAlignment", referenced from:
      _arglPixelFormatSet in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheBindTexture2D", referenced from:
      _arglPixelFormatSet in libHiARWrapper.a(gsub_es.o)
      _arglCleanup in libHiARWrapper.a(gsub_es.o)
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
      _arglPixelBufferDataUploadBiPlanar in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheDisableLighting", referenced from:
      _arglDispImage in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheTexEnvSrc0", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheDisableClientStateNormalArray", referenced from:
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
  "_glStateCacheActiveTexture", referenced from:
      _arglPixelFormatSet in libHiARWrapper.a(gsub_es.o)
      _arglCleanup in libHiARWrapper.a(gsub_es.o)
      _arglDispImageStateful in libHiARWrapper.a(gsub_es.o)
      _arglPixelBufferDataUploadBiPlanar in libHiARWrapper.a(gsub_es.o)
ld: symbol(s) not found for architecture arm64

这种unity里面静态库的错误的话 可以尝试修改Build Settings->Enable Testability为NO 我的项目中就遇到了这个坑 无论怎么改都是报这个错(应该是因为AR的SDK) 后来才发现导出的项目中这个值是NO我的原生项目中这个是YES

  • 如果出现诸如
duplicate symbol xxx in:

这种库冲突 可以看看你是否在Build Settings->Other Linker Flag中添加了-force_load 提及冲突的库 把冲突的项删除了

  • 启动APP日志报错Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application并且崩溃 注意你unity里面的屏幕方向在你的项目设置中Target->Deployment Info->Device Orientation是否支持
  • 如果CoreMotion这个库报错,在Build Setting->Other Linker Flags中添加-weak_framework CoreMotion -weak-lSystem (第一次导入项目的时候遇到过一次 后来重新导入的时候没遇到过 也没添加这句项目也跑起来了)
  • 如果unity项目中有用到照相机麦克风等要在info.plist中添加对应的请求允许使用键值对 否则会崩溃
  • 有些文档提到依赖库中AVFoundation、CoreMotion、iAd的Status都是Optional,其他的都是Required但是我的项目中没有修改依然运行成功,如果遇到莫名其妙的错误可以尝试
  • 如果你的项目是ARC的那么你如果按照有些文档中去设置了Build Setting->C Language DialectC99会导致__weak Self不识别等错误 事实上我没有设置这一步也运行成功了 就用默认的GNU99就可以 如果有需要为有需要的.mm文件打上MRC标签就好
  • 有些文档中提到的unityController里面的函数可能会跟你项目中有差异 注意根据实际情况使用
[_unityController Paused];
[_unityController setPaused:NO];//判断unity控制器的状态和改变状态
但是我的项目中就没有 取而代之的是
if (UnityIsPaused() == 1) {//判断状态 1暂停 0运行中
        UnityPause(0);//激活unity控制器 0激活 1暂停
}

参考文档
http://blog.csdn.net/dylan_lwb_/article/details/51452470
http://www.jianshu.com/p/f98bcfe09dc7
http://www.jianshu.com/p/6ddc80cfa3fc
http://www.jianshu.com/p/3d9ae5244d82
http://blog.csdn.net/qinqi376990311/article/details/72303053
http://blog.sina.com.cn/s/blog_48a8af640102vh2q.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容