unity2019版本融合iOS

基本思路:

Xcode 工程創(chuàng)建工作空間档痪,一個(gè)工作空間包含 iOS原生工程,一個(gè)為3D工程邢滑。通過UnityFramework.framework 進(jìn)行橋接通信腐螟。 unity工程注冊(cè)代理,原生實(shí)現(xiàn)交互方法困后、
unity 調(diào)取iOS 代理模式交互數(shù)據(jù)乐纸。
iOS調(diào)取unity 通過UnityFramework 提供的發(fā)送消息方法。

正文:
Unity 2019.3.a2及更高版本摇予,以及Xcode 9.4及更高版本汽绢。
下載Unity 2019.3.a2: https://unity3d.com/alpha/2019.3

1.生成iOS工程
首先在Unity編輯器打開UnityProject項(xiàng)目,選擇Menu -> Window -> Package Manager侧戴,因?yàn)?.0.8版本不兼容使用Unity作為庫宁昭,所以要移除Ads資源包,或更新Ads資源包到v 3.*版本酗宋。

選擇Menu -> Edit -> Player Settings -> Player -> iOS設(shè)置標(biāo)簽頁 -> Identification Section积仗,設(shè)置有效的Bundle Identification和Signing Team ID,以避免后續(xù)步驟出現(xiàn)Xcode簽名問題蜕猫。

打開Menu -> File -> Builds Settings寂曹,在此選擇并切換平臺(tái)為iOS。將UnityProject項(xiàng)目構(gòu)建到iosBuild文件夾丹锹。

2.創(chuàng)建Xcode工作空間
設(shè)置Xcode工作空間
  Xcode工作空間允許同時(shí)處理多個(gè)項(xiàng)目稀颁,并結(jié)合它們的結(jié)果芬失。
  我們?cè)赬code打開NativeiOSApp.xcodeproj楣黍。選擇File -> New -> Workspace,創(chuàng)建工作空間棱烂,把它保存在UaaLExample/both.xcworkspace租漂。

關(guān)閉NativeiOSApp.xcodeproj項(xiàng)目,此后的步驟會(huì)在剛創(chuàng)建的工作空間項(xiàng)目完成颊糜。

選擇File -> Add Files to “both”哩治,把NativeiOSApp.xcodeproj和第2步生成的Unity-iPhone.xcodeproj添加到相同等級(jí)的工作空間。

image.png

3.將iOS工程 加入工作空間
將unity導(dǎo)出工程加入工作空間
如果使用pod 將pods 工程加入工作空間
file -> addFile to ""


image.png

3個(gè)工作空間平級(jí)

  1. 添加UnityFramework.framework


    image.png

5.設(shè)置Data文件夾為 UnityFramework.framework 部分


image.png

6.公開橋接文件

image.png

工程配置完畢衬鱼。以下是代碼配置

  1. AppDelegate.mm 修改為 MM
    將 main.m 與AppDelegate 寫入同一個(gè)文件

     #include <UnityFramework/UnityFramework.h>
     #include <UnityFramework/NativeCallProxy.h>
     #include <mach/mach.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;
     }
    
     void showAlert(NSString* title, NSString* msg) {
       UIAlertController* alert = [UIAlertController     alertControllerWithTitle:title message:msg                                                             preferredStyle:UIAlertControllerStyleAlert];
         UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault
                                                       handler:^(UIAlertAction * action) {}];
         [alert addAction:defaultAction];
     //    auto delegate = [[UIApplication sharedApplication] delegate];
    
    
         UIViewController *vc = [UIApplication     sharedApplication].delegate.window.rootViewController;
    
       [vc presentViewController:alert animated:YES completion:nil];
     }
    
     int gArgc = 0;
     char** gArgv = nullptr;
     NSDictionary* appLaunchOpts;
    
    
           @interface AppDelegate : UIResponder<UIApplicationDelegate,     UnityFrameworkListener, NativeCallsProtocol>
    
     @property (strong, nonatomic) UIWindow *window;
     @property UnityFramework* ufw;
     @property (assign, nonatomic) BOOL isStartUnity ;
    
     - (void)initUnity;
     - (void)ShowMainView;
    
     - (void)didFinishLaunching:(NSNotification*)notification;
     - (void)didBecomeActive:(NSNotification*)notification;
     - (void)willResignActive:(NSNotification*)notification;
     - (void)didEnterBackground:(NSNotification*)notification;
     - (void)willEnterForeground:(NSNotification*)notification;
     - (void)willTerminate:(NSNotification*)notification;
     - (void)unityDidUnloaded:(NSNotification*)notification;
    
     @end
    
    
     @implementation AppDelegate
    
     - (bool)unityIsInitialized { return [self ufw] && [[self ufw] appController];               }
    
     #pragma mark - 打開3D
     - (void)showUnityView
         {
         if(![self unityIsInitialized]) {
     showAlert(@"Unity is not initialized", @"Initialize Unity first");
         } else {
             [[self ufw] showUnityWindow];
       }
     }
     #pragma mark - 打開原生
     - (void)showNativeView
       {
         [self.window makeKeyAndVisible];
       }
     #pragma mark - 發(fā)消息
           - (void)sendMsgToUnity:(NSString *)strClass method:(NSString     *)strMethod  value:(NSString *)strValue
         {
    
       //    [[self ufw] sendMessageToGOWithName: "Cube" functionName: "ChangeColor" message: "yellow"];
           [[self ufw] sendMessageToGOWithName:strClass.UTF8String functionName:strMethod.UTF8String message:strValue.UTF8String];
     }
    
    - (void)showHostMainWindow
    {
        [self showHostMainWindow:@""];
    }
    
    - (void)showHostMainWindow:(NSString*)color
    {
    //    if([color isEqualToString:@"blue"])        self.viewController.unpauseBtn.backgroundColor = UIColor.blueColor;
    //    else if([color isEqualToString:@"red"]) self.viewController.unpauseBtn.backgroundColor = UIColor.redColor;
    //    else if([color isEqualToString:@"yellow"]) self.viewController.unpauseBtn.backgroundColor = UIColor.yellowColor;
    
    //     [UIApplication sharedApplication].keyWindow.rootViewController = ;
    
    //    [self.window makeKeyAndVisible];
        [self showNativeView];
    }
    
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
    
    
        [self initUnity];
    
        if (@available(iOS 10.0, *)) {
     
    //        [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
    //            NSInteger appMemoryBytes = qs_getAppMemoryBytes();
    //            NSLog(@"使用了 %f MB 內(nèi)存", appMemoryBytes / 1024.0f/ 1024.0f);
    //        }];
        } else {
            // Fallback on earlier versions
        }
    
        return YES;
    }
    
    //獲取當(dāng)前App的內(nèi)存使用值
    uint64_t qs_getAppMemoryBytes() {
        task_vm_info_data_t vmInfo;
        mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
        kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO,        (task_info_t) &vmInfo, &count);
        if (result != KERN_SUCCESS)
            return 0;
        return vmInfo.phys_footprint;
    }
    #pragma mark - 初始化UnityManage
    
    #pragma mark - 初始化3D
    - (void)initUnity
    {
        if([self unityIsInitialized]) {
            showAlert(@"Unity already initialized", @"Unload Unity first");
            return;
        }
    
        [self setUfw: UnityFrameworkLoad()];
        [[self ufw] setDataBundleId: "com.unity3d.framework"];
        [[self ufw] registerFrameworkListener:self];
    
        [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
    
        [[self ufw] runEmbeddedWithArgc: gArgc argv: gArgv appLaunchOpts: appLaunchOpts];
    
    
        [NSTimer scheduledTimerWithTimeInterval:5 repeats:NO block:^(NSTimer * _Nonnull timer) {
        [self showUnityView];
        }];
    }
    - (void)unloadUnity
    {
        if(![self unityIsInitialized]) {
            showAlert(@"Unity is not initialized", @"Initialize Unity first");
        } else {
    //        [UnityFrameworkLoad() unloadApplicaion: true];
        }
    }
    
    #pragma mark - 釋放回調(diào)
    - (void)unityDidUnload:(NSNotification*)notification
    {
        NSLog(@"unityDidUnloaded called");
    
        [[self ufw] unregisterFrameworkListener: self];
        [self setUfw: nil];
     }
    
    
    - (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
    
    
    int main(int argc, char * argv[]) {
        NSString * appDelegateClassName;
    
        gArgc = argc;
        gArgv = argv;
    
        @autoreleasepool {
            if (false)
            {
         // run UnityFramework as main app
         id ufw = UnityFrameworkLoad();
         
         // Set UnityFramework target for Unity-iPhone/Data folder to make Data part of a UnityFramework.framework and call to setDataBundleId
         // ODR is not supported in this case, ( if you need embedded and ODR you need to copy data )
         [ufw setDataBundleId: "com.unity3d.framework"];
         [ufw runUIApplicationMainWithArgc: argc argv: argv];
     } else {
         // run host app first and then unity later
         UIApplicationMain(argc, argv, nil, [NSString stringWithUTF8String: "AppDelegate"]);
            }
        }
        return UIApplicationMain(argc, argv, nil, appDelegateClassName);
    }
    

采坑經(jīng)驗(yàn):
1.Data文件夾一定要 包含到 UnityFramework.framework 不然報(bào)錯(cuò)
2.NativeCallProxy.h 包含到 UnityFramework.framework 并且公開

  1. 報(bào)錯(cuò) # [MapFileParser.sh: Permission denied]
    此報(bào)錯(cuò)因文件權(quán)限問題導(dǎo)致
    執(zhí)行指令
    chmod +x /Users/......./MapFileParser.sh (MapFileParser.sh所在的目錄)
    4.unity啟動(dòng)成功 直接跳入3D頁面
    找到 unity工程中的幾處跳轉(zhuǎn) 全部注釋
    關(guān)鍵字 [window makeKeyAndVisible];
    image.png

    5.僵尸斷點(diǎn)會(huì)導(dǎo)致untiy工程內(nèi)存持續(xù)增加业筏。不要勾選
    image.png

demo 地址
鏈接: https://pan.baidu.com/s/1JFWjbrh2x-qAsCzMwLywLA
提取碼: 9a71

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鸟赫,隨后出現(xiàn)的幾起案子蒜胖,更是在濱河造成了極大的恐慌消别,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件台谢,死亡現(xiàn)場(chǎng)離奇詭異寻狂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)朋沮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門蛇券,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人樊拓,你說我怎么就攤上這事纠亚。” “怎么了筋夏?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵菜枷,是天一觀的道長。 經(jīng)常有香客問我叁丧,道長啤誊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任拥娄,我火速辦了婚禮蚊锹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稚瘾。我一直安慰自己牡昆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布摊欠。 她就那樣靜靜地躺著丢烘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪些椒。 梳的紋絲不亂的頭發(fā)上播瞳,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音免糕,去河邊找鬼赢乓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛石窑,可吹牛的內(nèi)容都是我干的牌芋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼松逊,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼躺屁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起经宏,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤犀暑,失蹤者是張志新(化名)和其女友劉穎熄捍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體母怜,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡余耽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了苹熏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碟贾。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖轨域,靈堂內(nèi)的尸體忽然破棺而出袱耽,到底是詐尸還是另有隱情,我是刑警寧澤干发,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布朱巨,位于F島的核電站,受9級(jí)特大地震影響枉长,放射性物質(zhì)發(fā)生泄漏冀续。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一必峰、第九天 我趴在偏房一處隱蔽的房頂上張望洪唐。 院中可真熱鬧,春花似錦吼蚁、人聲如沸凭需。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粒蜈。三九已至,卻和暖如春旗国,著一層夾襖步出監(jiān)牢的瞬間枯怖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國打工粗仓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嫁怀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓借浊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親萝招。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚂斤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 概述 在多數(shù)移動(dòng)應(yīng)用中任何時(shí)候都只能有一個(gè)應(yīng)用程序處于活躍狀態(tài),如果其他應(yīng)用此刻發(fā)生了一些用戶感興趣的那么通過通知...
    莫離_焱閱讀 6,498評(píng)論 1 8
  • iphone開發(fā)筆記 退回輸入鍵盤 - (BOOL) textFieldShouldReturn:(id)text...
    愛易寒曲易散閱讀 618評(píng)論 0 1
  • //設(shè)置尺寸為屏幕尺寸的時(shí)候self.window = [[UIWindow alloc] initWithFra...
    LuckTime閱讀 797評(píng)論 0 0
  • 2019年的520槐沼,別人在朋友圈里曬男朋友曙蒸,而我曬我的消消樂捌治。 我用行動(dòng)證明我是快樂的單身狗。 520這一天讓我想...
    念憶往昔閱讀 764評(píng)論 0 1
  • 今天我們語文學(xué)了小青蛙纽窟,生字肖油,數(shù)學(xué)學(xué)了鐘表,還有圍棋
    郭宇妍閱讀 96評(píng)論 0 0