Unity項目集成到現有iOS項目
1.將Unity項目文件復制到到iOS項目跟目錄下
主要有5個文件,Classes,Data,Libraries,MapFileParser,MapFileParser.sh,(前三個是文件夾)。
2.在iOS項目中添加文件引用
(1)對Classes,Libraries,MapFileParser.sh添加
注意這里是在app的根目錄下,右鍵“Add File to ...”
,選中三個文件(文件夾),記住在options里面勾選“Create groups”
,“Copy items if needed”
就不用選中了。
(2) 對Data添加
同樣是在app的根目錄下,右鍵添加文件,選中Data文件夾,但是這里的options,是選“Create folder references”
,記住了,別選錯。
完成這兩步之后,項目工程應該是這樣子。
3.刪除項目文件.h文件,跟libil2cpp的引用
(1)
在iOS項目中,找到Classes->Native
目錄,將目錄下的.h
文件全部刪除引用,注意只是.h
,因為里面還有.cpp
,這里只需要在Native
文件夾上右鍵選擇Sort by Type
就可以把.h
,.cpp
分開了。
。這里只是刪除引用,選擇這里面估計有幾千個文件慢慢等一下。
(2)
找到Libraries->libil2cpp
,刪除文件引用,同上面選擇Remove References
4.對工程TARGETS進行配置。
note:這里的全部配置,其實都可以參考Unity導出的項目去配置的
(1)添加引用庫
注意有3個是選擇optional的。
(2)添加頭文件,庫搜索路徑
在項目TARGETS->Build Settings
搜索Search。
在Header Search Paths
下添加以下路徑
"$(SRCROOT)/Classes"
"$(SRCROOT)"
$(SRCROOT)/Classes/Native
$(SRCROOT)/Libraries/bdwgc/include
$(SRCROOT)/Libraries/libil2cpp/include
在Library Search Paths
下添加以下路徑
"$(SRCROOT)"
"$(SRCROOT)/Libraries"
$(SRCROOT)/Libraries/Plugins/iOS
(3)配置Other Linker Flags
在Other Linker Flags
下添加以下關鍵字:
-weak_framework
CoreMotion
-weak-lSystem
Note:當項目中集成了多個第三方庫的時候,例如本次項目,需要集成百度地圖SDK,兩個庫之間的文件、文件內容可能有重復,這時候就會出現duplicate symbol
的警報后來我找到了篇文章去解決。iOS 解決一個因三方靜態庫沖突產生的duplicate symbol的問題
(4)C,C++,ObjC環境設置
這里的Prefix Header選擇自己項目的.pch文件距離,具體設置可以百度搜索。
(5)添加User-Defined設置
根據圖示
分別添加鍵值對。
GCC_THUMB_SUPPORT
-> NO
GCC_USE_INDIRECT_FUNCTION_CALLS
->NO
UNITY_RUNTIME_VERSION
->5.4.2f2
UNITY_SCRIPTING_BACKEND
->il2cpp
(6)添加Run Script
在Build Phases
頁面下左上角的加號,選擇New Run Script Phase
,然后在Run Script
進行配置.
Note:再說一遍,以上的所有項目TARGETS的配置,都可以在Unity導出的Xcode項目中參照著修改配置!!!
5.文件配置和修改
(1)pch文件
在Classes
文件夾下,可以找到Prefix.pch
文件。如果你有自己的pch文件,那就可以把這個文件里面的全部內容復制到自己的.pch
文件里面,如果你要使用它也可以,那就在上面設置設置Prefix Header的時候設置好使用的文件路徑就好。
(2)修改main文件
將Classes/
下的main.mm
文件里面的內容,全部復制到集成項目的Supporting Files/
下的main.m
文件中,然后刪除Classes/main.mm
,并且把文件后綴改成.mm
,。并且按照下圖對內容進行修改
(3)AppDelegate修改
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
文件修改
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
-(UIWindow *)unityWindow{
return UnityGetMainWindow();
}
-(void)showUnityWindow{
[self.unityWindow makeKeyAndVisible];
}
-(void)hideUnityWindow{
[self.window makeKeyAndVisible];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
_unityController = [[UnityAppController alloc] init];
[_unityController application:application didFinishLaunchingWithOptions:launchOptions];
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.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 throttle down OpenGL ES frame rates. 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 inactive 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
(4)UnityViewController修改
(1)
在Classes/
目錄下找到UnityAppController.h
文件,按照以下修改
將
inline UnityAppController* GetAppController()
{
return (UnityAppController*)[UIApplication sharedApplication].delegate;
}
修改成
#import "AppDelegate.h"
inline UnityAppController* GetAppController()
{
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
return delegate.unityController;
}
(2)如果有Main.storyboard就把它移除。
6.啟動和隱藏Unity界面
//進入unity界面
[(AppDelegate *)[UIApplication sharedApplication].delegate showUnityWindow];
UnityPause(false);
//推出Unity界面
[(AppDelegate *)[UIApplication sharedApplication].delegate hideUnityWindow];
UnityPause(true);
7.問題收集
(1)在使用Unity攝像頭的時候黑屏
問題表現為,在使用Unity打包出來的項目運行是正常的,但是集合到現有項目的時候,攝像頭顯示區域是黑屏。錯誤碼是:EasyAR is running on an unsupported graphics device of type -4
。
解決的方法:
1.在UnityAppController.h
中添加以下兩個方法
extern "C" void ezarUnitySetGraphicsDevice(void* device, int deviceType, int eventType);
extern "C" void ezarUnityRenderEvent(int marker);
2.在UnityAppController.mm
中添加這兩個方法
3.在UnityAppController.mm
實現以下方法
- (void)shouldAttachRenderDelegate
{
UnityRegisterRenderingPlugin(&ezarUnitySetGraphicsDevice, &ezarUnityRenderEvent);
}
(2)按照上文啟動Unity的窗口,后來我發現,這個Unity的窗口其實在你主app窗口下面一直運行,知道你第一次使用暫停,這里會使得手機發燙,一直占用資源。
解決方法:
我在UnityAppController.mm
的- (void)startUnity:(UIApplication*)application
最后添加了UnityPause(true);
使得Unity在初始化完成之際,馬上停止界面,稍微對情況有所改善,如果有更好的方法,希望在下面留言。