最近用`Unity2017`打包的文件嵌入到現(xiàn)有`iOS`工程中發(fā)現(xiàn)也是可以的,更加方便侯嘀。出現(xiàn)的問題在最底下已經(jīng)解決偏窝。
因為現(xiàn)有項目有個功能需要調(diào)用Unity
頁面,所以就叫同事用Unity
打一個包給我嵌入到現(xiàn)有iOS
工程究孕,就一個導入過程就非常曲折比搭。(淚奔~~o(>_<)o ~~)
以下所有的文件結(jié)構(gòu)和TARGETS
配置都是參考Unity
導出來的工程結(jié)構(gòu)和配置冠跷,后面所有的刪除都是刪除引用。
1,首先將導出的包跑一下看看能不能跑起來(注意打出來的包是否支持模擬器運行)蜜托,能跑起來才做下面的將Unity
項目下面的四個文件復(fù)制到iOS
項目的根目錄
Unity打包出來的包
復(fù)制到iOS
的項目后的目錄如下:
復(fù)制到iOS項目后的目錄結(jié)構(gòu)
2弟疆,在自己iOS
項目中引用這幾個文件,但是引用跟我們平時引用的不一樣,右鍵Add Files to ···
分別選擇Classes
和 Libraries
盗冷、MapFileParser.sh
,在Options
里面勾選 Create groups
同廉,不要選Copy items if needed
引用文件
2.1仪糖,剩下的Data
文件,右鍵Add Files to ···
迫肖,在Options
里面勾選 Create folder references
锅劝,不要選Copy items if needed
Data導入
完成之后的文件夾目錄如下:
目錄,以這個為準
2.2蟆湖,接下來刪除多余的引用:
在Classes
->Native
目錄故爵,將目錄下的.h
文件全部刪除(注意:只刪除引用,而且只有.h
隅津,因為里面還有.cpp
诬垂,據(jù)說Unity
2017不用刪除,但是我還沒有測試成功)
2.2
2.3伦仍,再刪除Libraries
->libil2cpp
,這個文件的引用结窘,同上面操作步驟一樣的
2.3
3,對iOS
工程環(huán)境的配置,這里的配置都是以Unity
的配置為參考
3.1充蓝,添加應(yīng)用庫
3.1
3.2隧枫,添加頭文件和庫的搜索路徑
3.2
每一個項目的配置和路徑不一樣,這里只是參考谓苟,一切以你
Unity
項目的配置為準2.41
3.3官脓,其它一些配置
3.3.1
3.3.2
3.3.3
3.3.4
3.3.5
3.3.6
上面注意:如果自己的
iOS
項目有pch
文件,那就把Prefix.pch
里面的文件拷貝到自己的pch
文件中涝焙,反之也行(注意pch路徑)卑笨,并添加#import"UnityAppController.h"
pch文件
3.3.7
3.4,添加用戶定義的設(shè)置(這個圖是我用Unity
2017來試的時候截的圖仑撞,但是失敗了湾趾,5.6可以)
3.4
4,修改main.m
文件
把Classes/
文件夾里面的main.mm
里面的代碼派草,拷貝到Supporting Files/
下的main.m
文件中搀缠,并把后綴改成.mm
,修改如下圖
4
然后刪除
Classes
目錄下單main.mm
文件近迁。注意:一樣是刪除引用到了這里基本集成完畢了~~~
5艺普,修改AppDelegate
文件
AppDelegate.h
文件
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UnityAppController * unityController;
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UIWindow * unityWindow;
- (void)showUnityWindow;
- (void)hideUnityWindow;
@end
AppDelegate.m
文件
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (UIWindow *)unityWindow {
return UnityGetMainWindow();
}
- (void)showUnityWindow {
UIButton * btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@"返回iOS世界" forState:UIControlStateNormal];
[btn setFrame:CGRectMake(100, 100, 100, 40)];
[btn addTarget:self action:@selector(hideUnityWindow) forControlEvents:UIControlEventTouchUpInside];
[self.unityWindow addSubview:btn];
[self.unityWindow makeKeyAndVisible];
}
- (void)hideUnityWindow {
[self.window makeKeyAndVisible];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
self.window.rootViewController = nav;
self.unityController = [[UnityAppController alloc] init];
[self.unityController application:application didFinishLaunchingWithOptions:launchOptions];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
[_unityController applicationWillResignActive:application];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
[_unityController applicationDidEnterBackground:application];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
[_unityController applicationWillEnterForeground:application];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
[_unityController applicationDidBecomeActive:application];
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[_unityController applicationWillTerminate:application];
}
@end
6,修改UnityAppController.h
文件
#import "AppDelegate.h"
inline UnityAppController* GetAppController()
{
AppDelegate * delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
return delegate.unityController;
// return (UnityAppController*)[UIApplication sharedApplication].delegate;
}
7,啟動Unity
界面
進入Unity
界面
[(AppDelegate *)[UIApplication sharedApplication].delegate showUnityWindow];
UnityPause(false);
跳出Unity
界面
[(AppDelegate*)[UIApplication sharedApplication].delegate hideUnityWindow];
UnityPause(true);
8歧譬,一些報錯匯總:
1岸浑,報錯:libil2cpp/include/codegen/il2cpp-codegen.h:368:1: Control may reach end of non-void function
添加 return NULL;
2,編譯時遇到Permission denied錯誤的是因為當前開發(fā)賬號對項目目錄沒有權(quán)限執(zhí)行MapFileParser.sh
解決方法:chmod +x /Users/......./MapFileParser.sh (MapFileParser.sh所在的目錄)
3瑰步,clang: error: no such file or directory: 'CoreMotion'矢洲,注意Other Linker Flags的導入的順序
4,加了extern "c",卻不認識缩焦,一直報少“(”读虏,在Build Settings選項中找到Compile Sources As這項設(shè)置成Objective-C++ 就解決問題了
5,最近使用Unity2017打包的導入發(fā)現(xiàn)出現(xiàn)如下錯誤
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x146746d0>) doesn't contain a view controller with identifier 'unitySplashStoryboard''
解決辦法如下:在SplashScreen.mm文件修改下面的方法
void ShowSplashScreen(UIWindow* window)
{
// bool hasStoryboard = [[NSBundle mainBundle] pathForResource: @"LaunchScreen" ofType: @"storyboardc"] != nullptr;
//
// if (hasStoryboard)
// {
// UIStoryboard *storyboard = [UIStoryboard storyboardWithName: @"LaunchScreen" bundle: [NSBundle mainBundle]];
// _controller = [storyboard instantiateViewControllerWithIdentifier: @"unitySplashStoryboard"];
// }
// else
_controller = [[SplashScreenController alloc] init];
[_controller create: window];
[window makeKeyAndVisible];
}
最后感謝這兩位作者的引導文章:
Unity(2017版本)嵌入現(xiàn)有iOS工程
unity與iOS合并
iOS (Swift)集成 Unity步驟和各種填坑袁滥。