iOS项目集成unity工程

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


第一步

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

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

第二步

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

unity文件.png

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

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


    iOS项目集成unity工程_第1张图片
    导入Data.png
  • 另外三个选择Creat Groups

第三步

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

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

第四步

工程配置

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

iOS项目集成unity工程_第5张图片
  • 我的项目只添加了上面两项就运行成功了 但是其他文档中有些提及到还要添加
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的内容一定要放在如下部分

iOS项目集成unity工程_第6张图片

否则放外面的话会报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 
#import "UnityAppController.h"
@interface AppDelegate : UIResponder 

@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

你可能感兴趣的:(iOS项目集成unity工程)