unity版本 2017.1.1f1 Xcode版本8.2.1 (8C1002)
第一步
导出unity的Xcode工程(具体导出设置可以看文章末尾的链接大多数都有讲到设置) 此时需要注意的是
- Bundle ID 要与你iOS项目保持一致(一定要一致否者可能会报很多莫名其妙的错误)
第二步
将导出的unity工程中的以下四个文件导入到你的项目中 (如果是旧版unity可能还有一个MapFileParser文件)
注意 千万不要选错导入方式
-
Data一定要是这样选择导入(导入完成后Data是蓝色的文件夹)
- 另外三个选择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"
也是可以的 并且应该以导入项目时的路径为准不是照着这个写(具体思路见下面设置头文件路径)
第四步
工程配置
- 关闭bitcode。(已经关闭的可以忽略)新版的Unity已经支持Bitcode但你unity项目中的某些SDK可能并不支持,不关闭无法正常编译。
- 添加
Build Settings
中 Header Search Paths 和 Library Search Paths
- 需要特别强调一下 这里有个坑 这里的路径是你自己第二步中导入的四个文件的路径,你导入的路径是什么这里就写什么 不是照着我的写 比如文件路径是下面这样的
那么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
等一系列错误
-
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 添加了以后就可以正常运行了
- 添加自定义设置
UNITY_RUNTIME_VERSION -> xxx(你导出的unity项目中对应的版本号)
UNITY_SCRIPTING_BACKEND -> il2cpp
- 我的项目只添加了上面两项就运行成功了 但是其他文档中有些提及到还要添加
MTL_ENABLE_DEBUG_INFO -> NO (这个是本来就有的修改就行)
GCC_THUMB_SUPPORT NO
GCC_USE_INDIRECT_FUNCTION_CALLS NO
- 将iOS原生项目中的pch文件合并到
Classes/Prefix.pch
中,并且在Build Settings->Prefix Header
中设置路径(如果没有就不做合并但是仍然要设置unity项目的pch路径)
- 合并的时候需要注意 你原本项目中pch的内容一定要放在如下部分
否则放外面的话会报unknown type name 'NSString'之类的错
- 复制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
等错
- 修改启动函数(从我们自己的AppDelegate启动)在修改后的main.mm中
找到
UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
将之修改为
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
此时再启动的话就是走我们原来的AppDelegate了
- 添加跳转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 Dialect
为C99
会导致__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