集成unity2019.3.0f1版本打出的Xcode项目

前面我已经总结了2018版集成unity的方式、当时也有framework集成的方式,不过都很麻烦,每次都需要重新生成新的framework。
而2019版替我们省略了打包framework的步骤,相比2018版,集成快乐了许多。
集成过程如下:

1.使用Xcode工程生成.xcworkspace文件,并放到指定的文件夹下。

2.想iOS项目和unity导出的工程也放到和xcworkspace一样的文件下。


屏幕快照 2020-07-08 下午4.06.38.png

3.打开.xcworkspace文件 分别将unity的.xcodeproj和iOS项目的.xcodeproj添加进来(有pod的话,将Pods->Pods.xcodeproj也添加进来)


屏幕快照 2020-07-08 下午4.10.10.png

4.选择Data文件并打开右侧编辑栏 勾选UnityFramework 如图:


屏幕快照 2020-07-08 下午4.12.27.png

5.选择Librarise->Plugins->iOS->NativeCallProxy.h(这个文件主要写unity和原生的桥接方法)并打开右侧编辑栏 勾选UnityFramework 并选择public 将NativeCallProxy.m也勾选UnityFramework


屏幕快照 2020-07-08 下午4.15.42.png

6.这里我们选择UnityFramework先编译一下(因为这里我之前遇到了一个错误,错误信息:-> applicationDidFinishLaunching()
[libil2cpp] ERROR: Could not open /var/containers/Bundle/Application/EF905A34-3E68-47BD-9578-3D492F0FAF22/NativeiOSApp.app/Frameworks/UnityFramework.framework/Data/Managed/Metadata/global-metadata.dat
IL2CPP initialization failed,这是因为UnityFramework不对,解决的方式就是重新编译了UnityFramework,然后iOS工程重新引用UnityFramework就好了,这里说一下,以免大家踩坑)


屏幕快照 2020-07-08 下午4.17.37.png

7.选择iOS工程并添加UnityFramework 如图:


image.png

到这里文件相关的就可以不用管了(相较于2018版真是太省事了,unity的文件不用改也不用删,爽!!!)
接下来就是调用unity的实现了。

8.集成了unity后 iOS项目就不需要main.m文件了 可以将它删除了。找到AppDelegate.m文件 将它修改为.mm文件,然后将里面代码修改如下:

AppDelegate.mm

#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);
}

AppDelegate.h

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
- (void)showUnityView;
- (void)showNativeView;
- (void)sendMsgToUnity:(NSString *)strClass method:(NSString     *)strMethod  value:(NSString *)strValue;
@end

到这里就可以实现unity和原生的切换了,相比2018版,集成方便了,归根结底就是unity导出的Xcode工程会多一个UnityFramework,可以理解为unity帮我们将unity工程打包成一个framework,我们调用unity的所有方法都可以通过它去实现。而且2018集成的方式不但麻烦,需要改unity的文件代码,而且当unity和iOS两方工程的文件和依赖库都增加时,会使iOS工程debug模式下无法编译通过,会报‘ARM64 branch out of range (xxxxx max is +/-128MB)’的错误,意思就是文件太多了,改成release模式就可以编译了,但开发起来没法调试。


image.png

参考
参考
参考

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