iOS原生集成unity—framework形式集成(一)

以下所有內(nèi)容均為個(gè)人觀點(diǎn),轉(zhuǎn)載請(qǐng)注明出處<簡(jiǎn)書(shū)--小蝸牛吱呀之悠悠 >,謝謝谁帕!

最近需要在原生項(xiàng)目集成unity導(dǎo)出的工程,并作為子模塊存在冯袍,網(wǎng)上教程不少雇卷,大多數(shù)都嘗試了一遍,但都不能用,最終关划,還是總結(jié)出一套最為簡(jiǎn)單、快速翘瓮、有效的方法贮折。

一、背景

unity導(dǎo)出的工程资盅,不僅可以以APP的形式獨(dú)立上線调榄,同時(shí)也可以將其囊括成framework的形式,集成進(jìn)入我們已有的原生工程中呵扛,下面?zhèn)€將介紹已有原生上線項(xiàng)目每庆,如何集成unity。
unity的集成有三種方式:

1今穿、直接拖拽導(dǎo)入

這種方式網(wǎng)上資料很多缤灵,但我嘗試后都失敗了,也許與我這邊使用的unity版本有關(guān)蓝晒,此處不再贅述

2腮出、將unity作為一個(gè)target導(dǎo)入,并建立關(guān)聯(lián)

此方法也資料很多芝薇,仍然沒(méi)有成功
上述兩種方法我這邊都失敗了胚嘲,目前初步猜測(cè)是與使用的unity版本有關(guān),如有大神知道原因洛二,歡迎留言~

3馋劈、將unity囊括成framework,并將unity的內(nèi)容作為子項(xiàng)目導(dǎo)入到原生的workspace中晾嘶,并建立兩者之間的關(guān)聯(lián)妓雾。

二、準(zhǔn)備工作

1变擒、確認(rèn)當(dāng)前使用的unity版本是否高于2019.3.a2君珠,如果低于此版本,本文將不適用娇斑,建議使用上述方式1策添、2。Xcode版本需要大于9.4毫缆,作者使用的是11.5版本唯竹。
2、unity導(dǎo)出環(huán)境配置

a. 首先在Unity編輯器打開(kāi)UnityProject項(xiàng)目苦丁,選擇Menu -> Window -> Package Manager浸颓,因?yàn)?.0.8版本不兼容使用Unity作為庫(kù),所以要移除Ads資源包,或更新Ads資源包到v 3.*版本产上。
b. 配置Bundle Identification和Signing Team ID棵磷,此步驟非必須,可以在導(dǎo)出后再配置晋涣,但作者是統(tǒng)一配置的仪媒,所以也一并提一下。
選擇Menu -> Edit -> Player Settings -> Player -> iOS設(shè)置標(biāo)簽頁(yè) -> Identification Section

c.導(dǎo)出unity項(xiàng)目時(shí)谢鹊,要注意區(qū)分是否支持模擬器算吩,此處特別重要,如果弄錯(cuò)了佃扼,將導(dǎo)致后續(xù)集成失敗偎巢,如果你的原生工程是真機(jī)調(diào)試,那直接導(dǎo)出真機(jī)的工程即可兼耀。

正確導(dǎo)出unity工程后压昼,就可以開(kāi)始進(jìn)行集成了

三、集成

集成分為兩個(gè)步驟:workspace配置 翠订、代碼配置
如果你的原生項(xiàng)目使用的是cocopods巢音,直接跳過(guò)此1.1步驟,從1.2開(kāi)始尽超。

1.1workspace配置

此步驟為沒(méi)有使用cocopods的項(xiàng)目集成用官撼,將原生工程和unity導(dǎo)出的工程放在同一個(gè)文件夾中,如下圖


項(xiàng)目放在同一個(gè)文件夾下.png

打開(kāi)原生項(xiàng)目似谁,左上角點(diǎn)擊File->New->workspace傲绣,并建立的workspace保存在上圖中統(tǒng)一文件加下


新建workspace

此時(shí),關(guān)閉原生工程巩踏,打開(kāi)新建的workspace秃诵,點(diǎn)擊Xcode左下角的"+"號(hào),將原生工程塞琼、unity導(dǎo)出的工程添加進(jìn)來(lái)
導(dǎo)入workspace

導(dǎo)入完成后菠净,請(qǐng)從步驟2繼續(xù)集成

1.2原生項(xiàng)目有使用cocopods

將unity導(dǎo)出的工程拷貝到原生工程文件夾中,得到如下圖結(jié)構(gòu)


拷貝unity工程

打開(kāi)workspace彪杉,點(diǎn)擊Xcode左下角的"+"號(hào)毅往,將unity導(dǎo)出的工程添加進(jìn)來(lái)


導(dǎo)入unity
2.將unity工程集成為UnityFramework.framework

a.展開(kāi)unity原生工程,在products文件夾下找到UnityFramework.framework派近,右擊show in finder


UnityFramework.framework路徑

b.在workspace中選中nativeiOS工程文件攀唯,點(diǎn)擊下圖的“+”號(hào)


點(diǎn)擊加號(hào)

添加其他
此操作比較關(guān)鍵,很多人找不到UnityFramework.framework渴丸。打開(kāi)剛才UnityFramework.framework的路徑文件夾侯嘀,直接將文件夾拖拽進(jìn)剛才的路徑查找器中
拖進(jìn)去

添加完成以后另凌,注意檢查一下下圖項(xiàng)


image.png

此時(shí),你的原生空間下的Frameworks下將會(huì)出現(xiàn)UnityFramework.framework戒幔,且?guī)в姓归_(kāi)箭頭吠谢,否則就是錯(cuò)誤的


有箭頭
3.配置UnityFramework.framework和橋接文件

a.選中unity工程Data文件夾,按下圖配置

image.png

b.選中unity工程下的NativeCallProxy.h文件溪食,按下圖配置囊卜,注意,需要public
好多同學(xué)說(shuō)NativeCallProxy.h文件找不到错沃,這里特別說(shuō)明一下:這個(gè)文件是需要在導(dǎo)出unity工程之前,將NativeCallProxy.h文件導(dǎo)入雀瓢,然后再導(dǎo)出unity工程枢析;并且這個(gè)文件是不可以在unity工程導(dǎo)出后添加的,因?yàn)閡nity導(dǎo)出過(guò)程刃麸,會(huì)建立NativeCallProxy.h與unity工程的關(guān)聯(lián)醒叁,后期添加則沒(méi)有這個(gè)關(guān)聯(lián),編譯不通過(guò)
image.png

c.build一下UnityFramework.framework泊业,這一步一定要把沼,否則容易出現(xiàn)文件找不到的問(wèn)題
image.png

到這里為止,整個(gè)工程的配置就結(jié)束了吁伺,build一下你的原生工程饮睬,正常情況下是OK的,接下來(lái)就是代碼的配置

四篮奄、背景

1捆愁、新建一個(gè)繼承于NSObject的單例類(lèi),并添加以下兩個(gè)屬性

@property (nonatomic, assign) int gArgc;
@property (nonatomic, assign) char** gArgv;

2窟却、打開(kāi)main.m文件昼丑,在main函數(shù)中添加下面代碼,ConfigObj.h為剛才新建的單例類(lèi)

[ConfigObj shareInstance].gArgc = argc;
[ConfigObj shareInstance].gArgv = argv;

3夸赫、打開(kāi)AppDelegate.h文件菩帝,添加以下代碼

#import <UIKit/UIKit.h>
#include <UnityFramework/UnityFramework.h>

#include <UnityFramework/NativeCallProxy.h>
#import "ConfigObj.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate,UnityFrameworkListener, NativeCallsProtocol>
@property (strong, nonatomic) UIWindow *window;
@end

打開(kāi)AppDelegate.m文件,添加以下代碼

#import "AppDelegate.h"

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;
}
@interface AppDelegate ()
@property (nonatomic, strong) UnityFramework *ufw;

@end

@implementation AppDelegate


- (bool)unityIsInitialized { return [self ufw] && [[self ufw] appController]; }
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self initUnityWithOptions:launchOptions];
    });
    return YES;
}

- (void)initUnityWithOptions:(NSDictionary *)launchOptions
{

    
    [self setUfw: UnityFrameworkLoad()];
    // Set UnityFramework target for Unity-iPhone/Data folder to make Data part of a UnityFramework.framework and uncomment call to setDataBundleId
    // ODR is not supported in this case, ( if you need embedded and ODR you need to copy data )
    [[self ufw] setDataBundleId: "com.unity3d.framework"];
    [[self ufw] registerFrameworkListener: self];
    [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
    
    [[self ufw] runEmbeddedWithArgc: [ConfigObj shareInstance].gArgc argv: [ConfigObj shareInstance].gArgv appLaunchOpts: launchOptions];
    
    UIView *view = [[[self ufw] appController] rootView];
    
}
- (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]; }
@end

集成后茬腿,你可能會(huì)發(fā)現(xiàn)呼奢,將unity作為你的子模塊啟動(dòng)時(shí),在加載unity的啟動(dòng)頁(yè)之前滓彰,會(huì)先加載一次原生的啟動(dòng)頁(yè)控妻,可以將SplashScreen.mm文件下ShowSplashScreen函數(shù)里下面的代碼注釋

        UIStoryboard *storyboard = [UIStoryboard storyboardWithName: launchScreen bundle: [NSBundle mainBundle]];

        // as we still support xcode pre-11 we must do this weird dance of checking for both sdk and runtime version
        // otherwise it fails to compile (due to unknown selector)
    #if (PLATFORM_IOS && defined(__IPHONE_13_0)) || (PLATFORM_TVOS && defined(__TVOS_13_0))
        if (@available(iOS 13.0, tvOS 13.0, *))
        {
            _controller = [storyboard instantiateInitialViewControllerWithCreator:^(NSCoder *coder) {
                return [[UnityViewControllerStoryboard alloc] initWithCoder: coder];
            }];
        }
        else
    #endif
        {
            _controller = [storyboard instantiateInitialViewController];
        }
有小伙伴聯(lián)系我說(shuō)想知道如何作為target存在于工程中,其實(shí)上述文章的集成方式本質(zhì)上還是target關(guān)聯(lián)的方式存在揭绑,結(jié)構(gòu)圖如下:
結(jié)構(gòu)圖

到這里弓候,整個(gè)集成就完成了郎哭,運(yùn)行一下,就可以展示unity的內(nèi)容了菇存,后面具體的unity交互內(nèi)容將另起文章說(shuō)明夸研。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市依鸥,隨后出現(xiàn)的幾起案子亥至,更是在濱河造成了極大的恐慌,老刑警劉巖贱迟,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姐扮,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡衣吠,警方通過(guò)查閱死者的電腦和手機(jī)茶敏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缚俏,“玉大人惊搏,你說(shuō)我怎么就攤上這事∮腔唬” “怎么了恬惯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)亚茬。 經(jīng)常有香客問(wèn)我酪耳,道長(zhǎng),這世上最難降的妖魔是什么才写? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任葡兑,我火速辦了婚禮,結(jié)果婚禮上赞草,老公的妹妹穿的比我還像新娘讹堤。我一直安慰自己,他們只是感情好厨疙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布洲守。 她就那樣靜靜地躺著,像睡著了一般沾凄。 火紅的嫁衣襯著肌膚如雪梗醇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天撒蟀,我揣著相機(jī)與錄音叙谨,去河邊找鬼。 笑死保屯,一個(gè)胖子當(dāng)著我的面吹牛手负,可吹牛的內(nèi)容都是我干的涤垫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼竟终,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蝠猬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起统捶,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榆芦,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后喘鸟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體匆绣,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年什黑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犬绒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兑凿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出茵瘾,到底是詐尸還是另有隱情礼华,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布拗秘,位于F島的核電站圣絮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雕旨。R本人自食惡果不足惜扮匠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凡涩。 院中可真熱鬧棒搜,春花似錦、人聲如沸活箕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)育韩。三九已至克蚂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筋讨,已是汗流浹背埃叭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悉罕,地道東北人赤屋。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓立镶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親益缎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谜慌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353