1. Create a blank Unity project and export the iOS project (UnityiOSDemo)
  2. Create a blank iOS project (iOSUnityDemo)
  3. Open Xcode and create xcWorkspace (iOS&&Unity)
  4. Import UnityiOSDemo and iOSUnityDemo into iOS&&Unity
  5. Select UnityiOSDemo scheme to compile, this step is to get unity framework.framework
  6. Select the Data directory in the UnityiOSDemo project and change Target Membership to UnityFramework
  7. Select the iOSUnityDemo project and add UnityFramework. Framework in General-Frameworks, Libraries, and Embedded Content
  8. Select iOSUnityDemo and delete UnityFramework.framework from build-Phases -Link Binary With Libraries
  9. At this point, the preparations are ready

How do I switch between iOS native pages and Unity pages

//

// AppDelegate.h

// iOSUnityDemo

//

// Created by YueQu on 2021/8/31.

//

#import <UIKit/UIKit.h>

#include <UnityFramework/UnityFramework.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate.UnityFrameworkListener>

@property (nonatomic.strong) UIWindow *window;

@property (nonatomic.strong) UnityFramework *ufw;

- (void)initUnity;

- (void)showUnityMainWindow;

- (void)showNativeMainWindow;

@end
Copy the code
#import "AppDelegate.h"

#import "ViewController.h"

#import <UnityFramework/UnityFramework.h>

/* UnityFrameworkLoad */

UIKIT_STATIC_INLINE 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;

}

@interface AppDelegate(a)

@property (nonatomic.strong) UIViewController *nativeRootVC;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Override point for customization after application launch.

    /* Save the parameters */
    [[NSUserDefaults standardUserDefaults] setValue:launchOptions forKey:@"launchOptions"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    self.nativeRootVC = [[UINavigationController alloc] initWithRootViewController:[ViewController new]];
    self.window.rootViewController = self.nativeRootVC;
    return YES;

}

- (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];
}

#pragma mark - Unity


- (BOOL)unityIsInitialized {

    return [self ufw] && [[self ufw] appController];
}

- (void)initUnity {

    /* Check if Unity has been initialized */
    if ([self unityIsInitialized]) return;

    /* Initialize Unity */
    self.ufw = UnityFrameworkLoad();
    [self.ufw setDataBundleId:"com.unity3d.framework"];
    [self.ufw registerFrameworkListener:self];
// [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
    NSString *argvStr = [[NSUserDefaults standardUserDefaults] valueForKey:@"argv"];
    char **argv;
    sscanf([argvStr cStringUsingEncoding:NSUTF8StringEncoding]."%p",&argv);
    int argc = [[[NSUserDefaults standardUserDefaults] valueForKey:@"argc"] intValue];
    NSDictionary *launchOptions = [[NSUserDefaults standardUserDefaults] valueForKey:@"launchOptions"];

    /* Initialize */
    [self.ufw runEmbeddedWithArgc:argc argv:argv appLaunchOpts:launchOptions];

}

/// Add navigation bar to unity page

- (void)unityRootVCAddNavgationController {
    UIViewController *rootVC = [[self ufw] appController].rootViewController;
    [[self ufw] appController].window.rootViewController = nil;
    [[self ufw] appController].window.rootViewController = [[UINavigationController alloc] initWithRootViewController:rootVC];
    [rootVC.navigationController setNavigationBarHidden:true];

}

/// Display unity page

- (void)showUnityMainWindow {

    self.window.hidden = YES;
    [self.ufw appController].window.hidden = NO;

    if(! [self unityIsInitialized]){
        NSLog(@"Unity is not initialized yet");
        return;
    }

    [self.ufw showUnityWindow];
    [self.ufw pause:false];

    // Add a navigation bar to the Unity page
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self unityRootVCAddNavgationController];
    });

    // iOS calls Unity
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.ufw sendMessageToGOWithName:"Canvas" functionName:"outputStr" message:"Hello, Message from iOS Native."];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self unityRootVCPushVC];
    });
}

/// display the native page

- (void)showNativeMainWindow {
    self.window.hidden = NO;
    [self.ufw appController].window.hidden = YES;
    self.window.rootViewController = self.nativeRootVC;
    [self.window makeKeyAndVisible];
}

/// simulate push from unity page

- (void)unityRootVCPushVC {
    UIViewController *foo = [[UIViewController alloc] init];
    foo.view.backgroundColor = [UIColor whiteColor];
    [[[self ufw] appController].rootViewController.navigationController pushViewController:foo animated:YES];
}

#pragma mark - UnityFrameworkListener

- (void)unityDidUnload:(NSNotification *)notification {

    NSLog(@"========== %s ============",__func__);
    [self.ufw unregisterFrameworkListener:self];
    [self setUfw:nil];
    [self.window makeKeyAndVisible];
}

- (void)unityDidQuit:(NSNotification *)notification {
    NSLog(@"========== %s ============",__func__);
}

@end
Copy the code

IOS calls the Unity method

// obj: GameObject name, method: Unity script function name MSG: function parameter, if multiple functions, can be converted to JSON string
void UnitySendMessage(const char* obj, const char* method, const char* msg);
Copy the code

Unity calls the iOS method

1. Add a plugin file to your Unity project Plugins, such as test.mm

//
// Test.m
// Unity-iPhone
//
// Created by YueQu on 2021/8/31.
//

#import <Foundation/Foundation.h>

extern "C" {

    void iOSLog(const char * message);
}

void iOSLog(const char * message) {

    NSLog(@ "% @"[NSString stringWithUTF8String:message]);
}
Copy the code

2. In the Unity project script, call the iOS method, for example

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.UI;

public class CallObjC : MonoBehaviour
{

    public InputField input;

#if UNITY_IPHONE
    // Declare the iOS method
    [DllImport("__Internal")]
    static extern void iOSLog(string message);

    [DllImport("__Internal")]
    static extern void iOSLog2(string message);

#endif

    public void onButtonClick()
    {
        outputStr("test");
        // Call the iOS method
        iOSLog(input.text);
	iOSLog2(input.text);
    }

    public void outputStr(string resultStr)
    {
        Debug.LogFormat("result string = {0}", resultStr); }}Copy the code