Integration Unity as a library in native iOS app

This post explains how to include Unity as a Library into native iOS application. You can read more about Unity as a Library .

Pre Requirements:

1. Get source

  • Clone or Download GitHub repo uaal-example. It includes
    4584391--508793--folderStructure.png

  • UnityProject - this is a simple demo project made with Unity which will be integrated to the standard iOS application. Assets / Plugins / iOS files used to communicate from Unity player to Native app

  • NativeiOSApp - this is simple Xcode single view application where we want to integrate our Unity project. It has some UI and is prepared to load player with UnityFrameworkLoad()

2. Generate Xcode project for iOS
Nothing new here just generate Xcode project as usual

  • from Unity Editor open UnityProject
  • remove or update Ads package to v 3.* (2.0.8 version is not compatible with Unity as a Library) (Menu / Window / Package Manager)
  • set valid Bundle Identification and Signing Team ID ( to avoid Xcode signing issues on later steps ) (Menu / Edit / Player Settings / Player / iOS Setting tab / Identification Section)
  • select and switch to platform iOS (Menu / File / Builds Settings)

  • Build inside UnityProject to iosBuild folder
    4584391--427012--image11.png

3. Setup Xcode workspace
Xcode workspace allows to work on multiple projects simultaneously and combine their products

  • open NativeiOSApp.xcodeproj from Xcode
  • create workspace and save it at UaaLExample/both.xcworkspace. (File / New / Workspace)4584391--427018--image8.png
  • close NativeiOSApp.xcodeproj project all Next steps are done from just created Workspace project
  • add NativeiOSApp.xcodeproj and generated Unity-iPhone.xcodeproj from step #2 to workspace on a same level ( File / Add Files to “both” ) 4584391--427021--image3.png

4. Add UnityFramework.framework
With this step we add Unity player in form of framework to NativeiOSApp, it does not change behavior of NativeiOSApp yet

  • selected NativeiOSApp target from NativeiOSApp project
  • in General / Embedded Binaries press +
  • select Unity-iPhone/Products/UnityFramework.framework
  • remove UnityFramework.framework from Linked Frameworks and Libraries ( select it and press - )4584391--427024--image1.png
2 Likes

5. Expose NativeCallProxy.h
Native application implements NativeCallsProtocol defined in following file.

  • find and select Unity-iPhone / Libraries / Plugins / iOS / NativeCallProxy.h
  • enable UnityFramework in Target Membership and set Public header visibility (small dropdown on right side to UnityFramework) 4584421--427027--image7.png

6. Make Data folder to be part of the UnityFramework
By default Data folder is part of Unity-iPhone target, we change that to make everything encapsulated in one single framework file.

  • change Target Membership for Data folder to UnityFramework
    4584421--427030--image4.png

  • (optional) after previous change for Unity-iPhone project to continue to work Unity player need to point to a new place where Data is located by calling from Unity-iPhone/MainApp/main.mm:
    [ufw setDataBundleId: "com.unity3d.framework"];
    On Demand Resources are not supported in this case. To make them work instead of the calls above you need to copy Data folder to your native application (With script at Build Phases) and skip a calls above since by default Data folder expected to be in mainBundle.
    4584421--427036--image9.png

2 Likes

Workspace is ready
Everything is ready to build, run and debug for both projects: Unity-iPhone and NativeiOSApp (select scheme NativeiOSApp or Unity-iPhone)
4584442--427042--image6.png

If all went successfully at this point you should be able to run NativeiOSApp:
4584442--427045--workspaceIsReady.png

Key point
Unity player is controlled with UnityFramework object. To get it you call UnityFrameworkLoad (it loads UnityFramework.framework if it wasn't, and returns singleton instance to UnityFramework class observe Unity-iPhone/UnityFramework/UnityFramework.h for its API ).
Observe UnityFrameworkLoad in: NativeiOSApp/NativeiOSApp/MainViewController.mm or in Unity-iPhone/MainApp/main.mm

#include <UnityFramework/UnityFramework.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])
    {
        // Initialize Unity for a first time
        [ufw setExecuteHeader: &_mh_execute_header];    

        // Keep in sync with Data folder Target Membership setting
        [ufw setDataBundleId: "com.unity3d.framework"];

    }
    return ufw;
}
3 Likes

One question, I’m a little new to unity, I’ve already exported my unity project but it does not include the Unityframewrok, is there a series of specific steps to export the project correctly? Greetings!

All Xcode generated projects with Unity version 2019.3.a2+ will have new structure: launcher+UnityFramework ( there is no specific steps to do for that), please double check your unity version.

It is true I have a version below, I had that it was the most stable version since the ones you mention is an alpha, but then I will update and follow the tutorial, thanks for the help

I experience this issue https://github.com/yurykorzun/unity-react-native-demo with XCode project generated with Unity >2017, I am going to try the library approach, hopefully it solves it

Hi bosses ,if my Unity3D project change,Which files I need to replace in the IOS project?or I need intergation again?

You need to upgrade your project to Unity 2019.3.a2+ version first and then generate Xcode project.

Thank you for your answer. I mean after integration, what should I do if my Unity needs to add new content? Replace or reintegrate

You do integration once then generation of Xcode project with Append and Replace from Unity will work just fine and you wont need to reintegrate again.

1 Like

Thank you very much, hope you give more detailed tutorials!:stuck_out_tongue:

I tried to follow this but I can't get it to work.

First of all my unity xcodeproj is missing the NativeProxyCall. In fact it is missing the whole Plugins folder, there is only Libraries and that's it.

Second, I don't understand how I can present a second ViewController as my Unity project.
I was expecting something similar to the Android one, which I got running just fine, where I "just" have to integrate the generated framework and then can push to UnityViewController (Similar to Activity under Android) but that seems not to be the case?

I got the issue with unity2019.a7 version.
MTLTextureDescriptor has width of zero.

1 Like

So I am an iOS developer more than I am a Unity developer. This sounds great but can you explain what functionally "Unity as a Library" provides? Maybe explain it with some use cases? At first glance this sounds too good to be true! ;)

For example, can I switch from my natively running iOS Apps view to a Unity running view and then back to my native iOS view again? I think the AR Ads use case was mentioned... Can I have my natively running iOS app switch to a visible Unity Engine C# view and then when the Unity AR Ad is finished can I switch back to my view running Objective C native code programmatically? Also, can those 2 views pass data back and forth to each other?

validateTextureDimensions, line 1074: error 'MTLTextureDescriptor has width of zero.'
```csharp
*extern "C" void CreateSystemRenderingSurfaceMTL(UnityDisplaySurfaceMTL surface)
extern "C" void CreateRenderingSurfaceMTL(UnityDisplaySurfaceMTL* surface)

so i add code
surface->targetW=[UIScreen mainScreen].bounds.size.width*2;
surface->targetH=[UIScreen mainScreen].bounds.size.height*2;
surface->systemW=[UIScreen mainScreen].bounds.size.width*2;
surface->systemH=[UIScreen mainScreen].bounds.size.height*2;

2==[UIScreen mainScreen].scale

why width and height==0?**
```

1 Like

Hi Friends,

I am checking with full project and running it on Xcode 10.1. When I run NativeIosApp scheme. It shows

error
'UnityFramework/UnityFramework.h' file not found

Its not loading UnityFramework class properly. I did all steps of loading UnityFramework.framework .

Can anybody knows how to fix this?

Thanks

4 Likes

Hey Everyone , i am trying to do all the needful with this project but facing the issue of
'MTLTextureDescriptor has width of zero.'

Can anyone help me out with this .
Thanks in advance.

me to ; look 16#,but,don’t know why?

Hey there. Thanks to all for letting us know about this issue! I have checked it and I can say that is a Unity Metal regression. Bug will be reported. For now you can use this workaround:
4709345--444971--Screenshot 2019-07-03 at 13.32.45.png
You can see that && params.renderW != 0 && params.renderH != 0 should be added to Unity-iPhone->Classes->Unity->DisplayManager.mm 145 line

3 Likes