How to embed Unity Framework into iOS App (Objective C or Swift)

How to embed Unity Framework into iOS App (Objective C or Swift)

Embed your unity project to your native iOS Application and make it work as a part of your iOS mobile application.

In this blog, I will explain how you can add UnityFramework which you can generate from Unity itself which can be easily integrated into your new or existing iOS project.

Since Unity has given support for UnityFramework from Unity 2019.3.0a8so you need that version. Right now it’s in Alpha version but soon it’s going to release a stable version as well.

I am assuming that you are aware about UnityHub and How you can install the different Unity Versions from it.

Let’s get started with the steps of integration.

Step 1: Create A Unity Project or Open Existing One

You can create a new Unity Project or Open your existing project in Unity 2019.3.0.a8 and above as older version do not have support of UnityFramework.

Step 2: Remove Unity Ads Framework

Here we need to remove the Unity Ads framework or we can use version 2.0.8 as that version has some iOS version fixes.

  • Window → Package Manager
  • Click on Ads
No alt text provided for this image

Step 3: Switch to iOS Platform if not already

  • File → Build Settings
  • Select your scene
  • In platform section select iOS
No alt text provided for this image

Step 4: Update Player Settings

click on the player settings from the build settings.

File → Build Settings → Player Settings → Other Settings

Make the following changes in other settings.

  • Set valid Bundle Identification and Code Signing Team ID (iOS Setting tab / Identification Section)
  • Uncheck Auto Graphic API and Add OpenGLES2
  • Disable Metal API Validation ( Some device may not have the Metal support so )
  • Scripting Language : IL2CPP
  • Target Device SDK : Device SDK
  • Target Minimum OS Version : 10.0
  • Keep other settings as it is.

We are ready now to build and generate iOS project which will also generate UnityFramework.

Step 5: Export iOS Project from Unity

  • From Build Settings,
  • Run in Xcode : Select the latest xCode version here
  • Run in Xcode as : Release
  • Keep other checkbox unchecked
  • Compression Method : Default
  • Click on “Build” and save you iOS Project with name “iOSBuild” in one folder
No alt text provided for this image

Step 6: Create a fresh Objective C/Swift Project in iOS

  • Open Xcode and create a single view application in it.
  • Disable BitCode from the project’s build settings.
  • Save the project in the same folder where you have iOSBuild.
  • Make sure both are at the same level in the directory.

Step 7: Create a Workspace

  • From xCode Create A Workspace with the name “NativeBridge.xcworkspace” and save in the same folder where you have the iOS Build
  • Close the xCode project and open workspace we just created.
  • add NativeiOSApp.xcodeproj and generated Unity-iPhone.xcodeproj to workspace on a same level
No alt text provided for this image

Step 8: Embed Unity Framework to Native App

Now here we are going to embed unity framework to our native app so for that we will add the unity framework in Embedded Binaries of project’s general settings.

  • Select Data Folder from Unity-iPhone
  • Go to inspector panel →Target Membership
  • Make sure it’s available for UnityFramework as well.
No alt text provided for this image
  • NativeiOSApp → General → Embedded Binaries
  • Click on Add and Select UnityFramework from there.
  • Make sure you remove the Unity Framework from Linked Framework and Libraries
No alt text provided for this image
No alt text provided for this image

Unity Framework Integration For Objective C Project

Here we need to modify 3 files so instead of explaining each method which is going to be very long I am simply adding the link of those files.

  • Remove main.m file from NativeIOS project.
  • Replace the main.mm file from Unity-iPhone with this main.mm file.
  • Add the following code to your AppDelegate.h file.
#import <UIKit/UIKit.h>
	

@interface AppDelegate : UIResponder <UIApplicationDelegate>
	

@property (strong, nonatomic) UIWindow *window;
	

- (void)initUnity;
- (void)ShowMainView;
@end
  • Add the following code to your AppDelegate.m file.
#import "AppDelegate.h"
//#include <UnityFramework/NativeCallProxy.h>
#include <UnityFramework/UnityFramework.h>

int gArgc = 0;
char** gArgv = NULL;
NSDictionary* appLaunchOpts;

int main(int argc, char * argv[]) {
    gArgc = argc;
    gArgv = argv;
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}


@interface AppDelegate ()<UnityFrameworkListener>
@property UnityFramework* ufw;
@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    appLaunchOpts = launchOptions;
    return YES;
}

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

- (bool)unityIsInitialized {
    return [self ufw] && [[self ufw] appController]; }
- (void)initUnity
{
    if([self unityIsInitialized]) {
        NSLog(@"Unity already initialized, Unload Unity first");
        return;
    }
    
    [self setUfw: UnityFrameworkLoad()];
    // Set UnityFramework target for Unity-iPhone/Data folder to make Data part of a UnityFramework.framework and uncomment call to setDataBundleId// ODR is not supported in this case, ( if you need embedded and ODR you need to copy data )
    [[self ufw] setDataBundleId: "com.unity3d.framework"];
    [[self ufw] registerFrameworkListener: self];
    //[NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self];
    
    [[self ufw] runEmbeddedWithArgc: gArgc argv: gArgv appLaunchOpts: appLaunchOpts];
    
}

- (void)ShowMainView
{
    if(![self unityIsInitialized]) {
        NSLog(@"Unity is not initialized Initialize Unity first");
    } else {
        [[self ufw] showUnityWindow];
    }
}



@end
  • Now we are ready to call the start method of UnityFramework.
  • You can call this methods on click of a button to start the Unity as part of your mobile application.
#import "ViewController.h"
#import "AppDelegate.h"

@interface ViewController ()
@end
@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
	    // Do any additional setup after loading the view.
}
- (IBAction)showUnity_Clicked:(id)sender {
	 [((AppDelegate *)[[UIApplication sharedApplication] delegate]) initUnity];
     [((AppDelegate *)[[UIApplication sharedApplication] delegate]) ShowMainView];
}

@end

Unity Framework Integration For Swift Project

Here we need to modify only 1 file which is AppDelegate.swift where we will write methods to initiate the UnityFramework from native swift app.

  • You can simply add methods to your AppDelegate.swift
import UIKit
import UnityFramework
	

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

	var window: UIWindow?
	    
	    
	//MARK:- Unity Methods
	var unityFramework:UnityFramework?
	    
	func unityFrameworkLoad() -> UnityFramework? {
	    let bundlePath = Bundle.main.bundlePath.appending("/Frameworks/UnityFramework.framework")
	    if let unityBundle = Bundle.init(path: bundlePath){
	        if let frameworkInstance = unityBundle.principalClass?.getInstance(){
	           return frameworkInstance
	           }
	        }
	        return nil
	    }
	    
	    func initAndShowUnity() -> Void {
	        if let framework = self.unityFrameworkLoad(){
	            self.unityFramework = framework
	            self.unityFramework?.setDataBundleId("com.unity3d.framework")
	            self.unityFramework?.runEmbedded(withArgc: CommandLine.argc, argv: CommandLine.unsafeArgv, appLaunchOpts: [:])
	            self.unityFramework?.showUnityWindow()
	        }
	    }
	

	    //MARK:- Application LifeCycle
	    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
	        // Override point for customization after application launch.
	        return true
	    }
	}
  • Now you can simply call the initAndShowUnity() method from AppDelegate and Unity will initialise and work as a part of your native swift app.

Thanks for reading the blog. I hope this will help you in understanding the UnityFramework Integration.

This is my first blog post so I really appreciate if you can give your views on how I can improve this further.

C B Mishra

Principal Consultant -Unity/AR/VR/MR/Android/IOS/WebGl/Metaverse/Multiplayer/Crypto/Game developer ...

12 个月

Can we integrate unity in native IOS on partial screen( some part of screen) ?

回复
Ninthukesan Paramanantham

Software Engineer | Graduate

1 年

Hi Malav S. I am working on a project where I have to integrate an existing Xcode project as a framework and its functionalities into an existing Unity application. So as an initial stage roughly, I created a unity application with just one button click event. When we press the button it should trigger the framework. I put the generated framework into Assets->Plugins->iOS. Then I wrote a C# script file to trigger the function which will start the Xcode application. But in the end, I ended up with an error it said that it could not find the function that I declared in the Xcode bridging swift file. I need some help to sort it out. Thank you in advance.

回复
Karine Vinette

Développeuse Web

2 年

Hello, your tuto is awesome and I would like to add the framework libManomotion to the project. How can I do that ?

回复
Jeff Yeung

IT Project Manager

2 年

Hi Malav S. I'm an IOS developer trying to integrate UNity game to my swift project using your method. But I'm having an issue with it. At some point, my app crash on launch with: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no storyboard/xib was provided.' I understand this post may be long time ago but i surely need some help. Thank you

回复

Thank you very much for this post, Malav! This is a huge help.

回复

要查看或添加评论,请登录

Malav S.的更多文章

  • MVVM for?iOS

    MVVM for?iOS

    Hello Everyone, Here is another article by me that explains my understanding of the different iOS Architecture. Every…

    4 条评论

社区洞察

其他会员也浏览了