iOS項目集成unity工程

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


第一步

導(dǎo)出unity的Xcode工程(具體導(dǎo)出設(shè)置可以看文章末尾的鏈接大多數(shù)都有講到設(shè)置) 此時需要注意的是

  • Bundle ID 要與你iOS項目保持一致(一定要一致否者可能會報很多莫名其妙的錯誤)

第二步

將導(dǎo)出的unity工程中的以下四個文件導(dǎo)入到你的項目中 (如果是舊版unity可能還有一個MapFileParser文件)

unity文件.png

注意 千萬不要選錯導(dǎo)入方式

  • Data一定要是這樣選擇導(dǎo)入(導(dǎo)入完成后Data是藍色的文件夾)


    導(dǎo)入Data.png
  • 另外三個選擇Creat Groups

第三步

  • 照著unity導(dǎo)出的項目中TARGETS ->Build Phases->Link Binary With Libraries的依賴庫
    在你自己的iOS原生項目中挨個添加依賴庫(已經(jīng)有了的就不用管它 千萬不要重復(fù) 也不要漏)
  • 如果有需要 在Build Phases中搜索.mm文件 在有需要的.mm文件上打上-fno-objc-arc(MRC標簽);
  • 然后添加腳本路徑

    這里需要注意一下寫成"$PROJECT_DIR/Smart_ticket_iOS/MapFileParser.sh"也是可以的 并且應(yīng)該以導(dǎo)入項目時的路徑為準不是照著這個寫(具體思路見下面設(shè)置頭文件路徑)

第四步

工程配置

  1. 關(guān)閉bitcode。(已經(jīng)關(guān)閉的可以忽略)新版的Unity已經(jīng)支持Bitcode但你unity項目中的某些SDK可能并不支持,不關(guān)閉無法正常編譯。
  2. 添加 Build SettingsHeader Search PathsLibrary Search Paths
  • 需要特別強調(diào)一下 這里有個坑 這里的路徑是你自己第二步中導(dǎo)入的四個文件的路徑,你導(dǎo)入的路徑是什么這里就寫什么 不是照著我的寫 比如文件路徑是下面這樣的
    文件路徑.jpg

    那么Header Search Paths就應(yīng)該添加
$(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應(yīng)該添加

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

如果unity的文件放在項目根目錄 那就應(yīng)該添加

$(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不需要特別設(shè)置 你導(dǎo)入文件的時候Xcode就會自動幫你設(shè)置好
    但是如果這個設(shè)置不對會出現(xiàn)library not found for -liPhone-lib之類的錯
  • Header Search Paths如果設(shè)置不對會出現(xiàn)
    'codegen/il2cpp-codegen.h' file not found等一系列錯誤
  1. Build Settings->Other C Flags添加-DINIT_SCRIPTING_BACKEND=1 如果無效可以嘗試把這個值移到最上面
  • 如果在最后編譯成功了 但是運行后卻在執(zhí)行unity代碼時日志打印was compiled with optimization - stepping may behave oddly; variables may not be available(其實這只是個警告并不是崩潰原因,這個警告是由于unity生成libiPhone-lib.a時使用了編譯優(yōu)化引起的)并崩潰可以嘗試添加-DRUNTIME_IL2CPP=1我的項目就是這樣 估計是因為添加了AR 添加了以后就可以正常運行了
  1. 添加自定義設(shè)置
UNITY_RUNTIME_VERSION -> xxx(你導(dǎo)出的unity項目中對應(yīng)的版本號)
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中設(shè)置路徑(如果沒有就不做合并但是仍然要設(shè)置unity項目的pch路徑)
  • 合并的時候需要注意 你原本項目中pch的內(nèi)容一定要放在如下部分


否則放外面的話會報unknown type name 'NSString'之類的錯

  1. 復(fù)制unity項目文件夾Classes中的main.mm文件中的代碼(所有),刪除你原生項目的main.m中的代碼(除了最開始的頭文件引用部分),將復(fù)制的內(nèi)容粘貼到原生項目的main.m中,刪除main.mm,修改main.m為main.mm(此時如果編譯成功運行的時候進入的是unity頁面 沒有走我們原生的AppDelegate)
  • 注意編譯請選擇真機 集成unity后不支持模擬器
  • 如果你忘記刪除main.mm會報沖突說你有兩個main
  • 如果你忘記修改main.m為main.mm會報'csignal' file not found等錯
  1. 修改啟動函數(shù)(從我們自己的AppDelegate啟動)在修改后的main.mm中
找到
UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: AppControllerClassName]);
將之修改為
UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

此時再啟動的話就是走我們原來的AppDelegate了

  1. 添加跳轉(zhuǎn)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 {
    在你的原有基礎(chǔ)上 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];
}

在導(dǎo)入的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"];
}

然后在需要調(diào)用unity的地方調(diào)用方法切換成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里面靜態(tài)庫的錯誤的話 可以嘗試修改Build Settings->Enable Testability為NO 我的項目中就遇到了這個坑 無論怎么改都是報這個錯(應(yīng)該是因為AR的SDK) 后來才發(fā)現(xiàn)導(dǎo)出的項目中這個值是NO我的原生項目中這個是YES

  • 如果出現(xiàn)諸如
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里面的屏幕方向在你的項目設(shè)置中Target->Deployment Info->Device Orientation是否支持
  • 如果CoreMotion這個庫報錯,在Build Setting->Other Linker Flags中添加-weak_framework CoreMotion -weak-lSystem (第一次導(dǎo)入項目的時候遇到過一次 后來重新導(dǎo)入的時候沒遇到過 也沒添加這句項目也跑起來了)
  • 如果unity項目中有用到照相機麥克風(fēng)等要在info.plist中添加對應(yīng)的請求允許使用鍵值對 否則會崩潰
  • 有些文檔提到依賴庫中AVFoundation、CoreMotion、iAd的Status都是Optional,其他的都是Required但是我的項目中沒有修改依然運行成功,如果遇到莫名其妙的錯誤可以嘗試
  • 如果你的項目是ARC的那么你如果按照有些文檔中去設(shè)置了Build Setting->C Language DialectC99會導(dǎo)致__weak Self不識別等錯誤 事實上我沒有設(shè)置這一步也運行成功了 就用默認的GNU99就可以 如果有需要為有需要的.mm文件打上MRC標簽就好
  • 有些文檔中提到的unityController里面的函數(shù)可能會跟你項目中有差異 注意根據(jù)實際情況使用
[_unityController Paused];
[_unityController setPaused:NO];//判斷unity控制器的狀態(tài)和改變狀態(tài)
但是我的項目中就沒有 取而代之的是
if (UnityIsPaused() == 1) {//判斷狀態(tài) 1暫停 0運行中
        UnityPause(0);//激活unity控制器 0激活 1暫停
}

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容