美文网首页
unity2019版本融合iOS

unity2019版本融合iOS

作者: Z小新 | 来源:发表于2020-04-22 14:58 被阅读0次

    基本思路:

    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

    相关文章

      网友评论

          本文标题:unity2019版本融合iOS

          本文链接:https://www.haomeiwen.com/subject/qhjiihtx.html