unity2019版本融合iOS

基本思路:

Xcode 工程创建工作空间,一个工作空间包含 iOS原生工程,一个为3D工程。通过UnityFramework.framework 进行桥接通信。 unity工程注册代理,原生实现交互方法、
unity 调取iOS 代理模式交互数据。
iOS调取unity 通过UnityFramework 提供的发送消息方法。

正文:
Unity 2019.3.a2及更高版本,以及Xcode 9.4及更高版本。
下载Unity 2019.3.a2: https://unity3d.com/alpha/2019.3

1.生成iOS工程
首先在Unity编辑器打开UnityProject项目,选择Menu -> Window -> Package Manager,因为2.0.8版本不兼容使用Unity作为库,所以要移除Ads资源包,或更新Ads资源包到v 3.*版本。

选择Menu -> Edit -> Player Settings -> Player -> iOS设置标签页 -> Identification Section,设置有效的Bundle Identification和Signing Team ID,以避免后续步骤出现Xcode签名问题。

打开Menu -> File -> Builds Settings,在此选择并切换平台为iOS。将UnityProject项目构建到iosBuild文件夹。

2.创建Xcode工作空间
设置Xcode工作空间
  Xcode工作空间允许同时处理多个项目,并结合它们的结果。
  我们在Xcode打开NativeiOSApp.xcodeproj。选择File -> New -> Workspace,创建工作空间,把它保存在UaaLExample/both.xcworkspace。

关闭NativeiOSApp.xcodeproj项目,此后的步骤会在刚创建的工作空间项目完成。

选择File -> Add Files to “both”,把NativeiOSApp.xcodeproj和第2步生成的Unity-iPhone.xcodeproj添加到相同等级的工作空间。

image.png

3.将iOS工程 加入工作空间
将unity导出工程加入工作空间
如果使用pod 将pods 工程加入工作空间
file -> addFile to ""


image.png

3个工作空间平级

  1. 添加UnityFramework.framework


    image.png

5.设置Data文件夹为 UnityFramework.framework 部分


image.png

6.公开桥接文件

image.png

工程配置完毕。以下是代码配置

  1. AppDelegate.mm 修改为 MM
    将 main.m 与AppDelegate 写入同一个文件

     #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 - 发消息
           - (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 内存", appMemoryBytes / 1024.0f/ 1024.0f);
    //        }];
        } else {
            // Fallback on earlier versions
        }
    
        return YES;
    }
    
    //获取当前App的内存使用值
    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 - 释放回调
    - (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);
    }
    

采坑经验:
1.Data文件夹一定要 包含到 UnityFramework.framework 不然报错
2.NativeCallProxy.h 包含到 UnityFramework.framework 并且公开

  1. 报错 # [MapFileParser.sh: Permission denied]
    此报错因文件权限问题导致
    执行指令
    chmod +x /Users/......./MapFileParser.sh (MapFileParser.sh所在的目录)
    4.unity启动成功 直接跳入3D页面
    找到 unity工程中的几处跳转 全部注释
    关键字 [window makeKeyAndVisible];
    image.png

    5.僵尸断点会导致untiy工程内存持续增加。不要勾选
    image.png

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知...
    莫离_焱阅读 6,489评论 1 8
  • iphone开发笔记 退回输入键盘 - (BOOL) textFieldShouldReturn:(id)text...
    爱易寒曲易散阅读 617评论 0 1
  • //设置尺寸为屏幕尺寸的时候self.window = [[UIWindow alloc] initWithFra...
    LuckTime阅读 791评论 0 0
  • 2019年的520,别人在朋友圈里晒男朋友,而我晒我的消消乐。 我用行动证明我是快乐的单身狗。 520这一天让我想...
    念忆往昔阅读 760评论 0 1
  • 今天我们语文学了小青蛙,生字,数学学了钟表,还有围棋
    郭宇妍阅读 95评论 0 0