最近公司打算將 unity 項(xiàng)目集成的 iOS 原生項(xiàng)目中坏逢,網(wǎng)上找了很多文章,大都集成復(fù)雜妙黍,關(guān)鍵是還不能成功集成悴侵。
許久,找到了一篇靠譜的文章拭嫁。和小伙伴摸索了好久終于集成成功可免。遂寫此文以供后人日后之用。
1.unity 項(xiàng)目導(dǎo)出iOS 項(xiàng)目
將你自己的 unity 項(xiàng)目或者參考文章中的unity 項(xiàng)目UnityProject按照下面的步驟來導(dǎo)出 iOS 項(xiàng)目做粤。
注意:unity 項(xiàng)目導(dǎo)出 iOS 項(xiàng)目可以有多種方式浇借,這里我們使用的是以 framework 庫(kù)的方式導(dǎo)出的,不清楚的可以詢問 unity 開發(fā)的小伙伴怕品。切記妇垢!我們摸索的時(shí)候就出現(xiàn)過類似坑點(diǎn)!
1.1
首先在Unity編輯器打開UnityProject項(xiàng)目肉康,選擇Menu -> Window -> Package Manager闯估,因?yàn)?.0.8版本不兼容使用Unity作為庫(kù),所以要移除Ads資源包吼和,或更新Ads資源包到v 3.*版本涨薪。
1.2
選擇Menu -> Edit -> Player Settings -> Player -> iOS設(shè)置標(biāo)簽頁(yè) -> Identification Section,設(shè)置有效的Bundle Identification和Signing Team ID炫乓,以避免后續(xù)步驟出現(xiàn)Xcode簽名問題刚夺。
1.3
打開Menu -> File -> Builds Settings,在此選擇并切換平臺(tái)為iOS末捣。將Unity項(xiàng)目導(dǎo)出 iOS 項(xiàng)目到一個(gè)文件夾光督。導(dǎo)出成功后該文件目錄如下:
2.創(chuàng)建 workspace并添加xcodeproj
workspace允許同時(shí)處理多個(gè)項(xiàng)目,并結(jié)合它們的結(jié)果塔粒。
2.1
我們打開 Xcode结借,選擇File -> New -> Workspace,創(chuàng)建工作空間integration.xcworkspace卒茬,把它保存在integrationProject目錄下船老。并按照下圖設(shè)置integrationProject目錄下的內(nèi)容咖熟,其中NativeiOSAPP為新建的空白的iOS 原生項(xiàng)目,當(dāng)然你也可以用已有的項(xiàng)目柳畔。UnityProject為 unity 導(dǎo)出的 iOS 項(xiàng)目馍管,即 1.3 中導(dǎo)出的那個(gè)文件夾。
2.2
打開integration.xcworkspace薪韩,選擇File -> Add Files to “integration”确沸,把NativeiOSAPP.xcodeproj和Unity-iPhone.xcodeproj添加到workspace 中。
3.添加UnityFramework.framework
這一步看似簡(jiǎn)單俘陷,實(shí)則是一個(gè)坑點(diǎn)罗捎。通過圖 3 圖 4直接添加UnityFramework.framework。如果添加后如圖 5一樣拉盾,UnityFramework.framework不是淺白色的就說明添加成功了桨菜。
如果是淺白色的話可以嘗試接下來的添加方法(我就是通過這種方法添加的)
先如下圖找到UnityFramework.framework的位置
然后將UnityFramework.framework文件夾拖到NativeiOSAPP的目錄下
成功后如下圖
4.設(shè)置NativeCallProxy.h
首先找到并選擇Unity-iPhone / Libraries / Plugins / iOS / NativeCallProxy.h。
然后在Target Membership中勾選UnityFramework捉偏,通過UnityFramework右側(cè)的下拉圖標(biāo)倒得,把標(biāo)頭可見性設(shè)為Public。
5.設(shè)置Data文件夾
默認(rèn)情況下夭禽,Data文件夾是Unity-iPhone目標(biāo)的一部分霞掺,我們會(huì)通過修改它,使所有內(nèi)容封裝到單個(gè)框架文件中讹躯。
我們把Data文件夾的Target Membership改為UnityFramework根悼。
改動(dòng)之后Unity-iPhone項(xiàng)目不能正常運(yùn)行,為了使Unity-iPhone項(xiàng)目能夠正常運(yùn)行蜀撑,我們需要在Unity-iPhone/MainApp/main.mm中通過下面代碼指定Data文件夾所處的新位置挤巡。
[ufw setDataBundleId: "com.unity3d.framework"];//com.unity3d.framework是UnityFramework的 bundleID。
至此酷麦,配置完畢矿卑!UnityFramework 也已經(jīng)集成到 iOS 原生項(xiàng)目中了。此時(shí)iOS 原生項(xiàng)目和 unity 導(dǎo)出的 iOS 項(xiàng)目應(yīng)該都能正常運(yùn)行了沃饶。
6.原生 iOS 項(xiàng)目中調(diào)用 unity
這里我們把 main.m改為 main.mm母廷,然后在Main.storyboard中 ViewController 上添加一個(gè)按鈕,點(diǎn)擊跳轉(zhuǎn)到 unity 工程糊肤。話不多說琴昆,直接上代碼。
main.mm
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
char ** aa = argv;
[[NSUserDefaults standardUserDefaults] setValue:@(argc) forKey:@"argc"];
[[NSUserDefaults standardUserDefaults] setValue:[NSString stringWithFormat:@"%p",aa] forKey:@"argv"];
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
AppDelegate.h
#import <UIKit/UIKit.h>
#include <UnityFramework/UnityFramework.h>
#include <UnityFramework/NativeCallProxy.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate,UnityFrameworkListener, NativeCallsProtocol>
@property (nonatomic, strong) UIWindow * window;
@property (nonatomic, strong) UnityFramework *ufw;
@end
AppDelegate.h
#import "AppDelegate.h"
@interface AppDelegate ()
@end
UnityFramework* UnityFrameworkLoad()
{
NSString* bundlePath = nil;
bundlePath = [[NSBundle mainBundle] bundlePath];
bundlePath = [bundlePath stringByAppendingString: @"/Frameworks/UnityFramework.framework"];
NSBundle* bundle = [NSBundle bundleWithPath: bundlePath];
if ([bundle isLoaded] == false) [bundle load];
UnityFramework* ufw = [bundle.principalClass getInstance];
if (![ufw appController])
{
// unity is not initialized
[ufw setExecuteHeader: &_mh_execute_header];
}
return ufw;
}
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[[NSUserDefaults standardUserDefaults] setValue:launchOptions forKey:@"launchOptions"];
self.ufw = UnityFrameworkLoad();
[self.ufw setDataBundleId:"com.unity3d.framework"];
[self.ufw registerFrameworkListener:self];
[NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
[[[self ufw] appController] applicationWillResignActive: application];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[[self ufw] appController] applicationDidEnterBackground: application];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
[[[self ufw] appController] applicationWillEnterForeground: application];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[[self ufw] appController] applicationDidBecomeActive: application];
}
- (void)applicationWillTerminate:(UIApplication *)application {
[[[self ufw] appController] applicationWillTerminate: application];
}
- (void)showHostMainWindow:(NSString *)color
{}
@end
ViewController.m
#import "ViewController.h"
#include <UnityFramework/UnityFramework.h>
#import "AppDelegate.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)pushToUnity:(id)sender {
NSString *argv = [[NSUserDefaults standardUserDefaults] valueForKey:@"argv"];
char ** aa;
sscanf([argv cStringUsingEncoding:NSUTF8StringEncoding], "%p",&aa);
int bb = [[[NSUserDefaults standardUserDefaults] valueForKey:@"argc"] intValue];
AppDelegate *dd = (AppDelegate *)([UIApplication sharedApplication].delegate);
[dd.ufw runEmbeddedWithArgc:bb argv:aa appLaunchOpts:[[NSUserDefaults standardUserDefaults] valueForKey:@"launchOptions"]];
}
@end
這樣集成就完成了馆揉!運(yùn)行iOS 原生項(xiàng)目就可以跳轉(zhuǎn)至 unity 了业舍。至于iOS 和 unity 之間的通信還在摸索之中。期待我神功大成吧。