集成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 
#include 
#include 

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

@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 

@interface AppDelegate : UIResponder 

@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

参考
参考
参考

你可能感兴趣的:(集成unity2019.3.0f1版本打出的Xcode项目)