Integrating Unity into a native iOS App

This Post describes the integration for Unity 4. If you are working with Unity 5 (which you should 😉 look at this post

For a full working sample with Unity 5 including source code look at this post

With Unity, its really easy to create and deploy stunning 3D-Apps. But what if you have a native iOS app, that is implemented in Objective-C, and only want to add unity-content only as a view?

Lucky us: With the new version of Unity, this is easier than ever.

The easiest way is to start your native app from the unity-generated XCode Project. Dont worry, its really easy to update the unity stuff within the app if it changes after the first export (which usually happens alot). This way round you dont have to set all the necessary build settings needed for unity on your own.

First thing you wanna do is change the Debug Format in the build settings from “DWARF with dSym” to “DWARF”. Otherwise you waste 30 seconds+ each build. Just keep in mind that you changed it if you need to change it back while debugging later.

Since everyone should use ARC nowadays, activate that in the buildsettings too. Make sure you add -fno-objc-arc to all .m and .mm files generated by unity (which are all of them at this state in the project).

Now create your own AppDelegate class by subclassing the Unity Version which is called UnityAppController. Your AppDelegate must be a .mm file. Generally the UnityAppController  takes care of everything related to the app-lifecycle so you wont need to implement that stuff. The only important stuff is to add

IMPL_APP_CONTROLLER_SUBCLASS(AppDelegate)

at the beginning of AppDelegate.mm. (FYI this macro is defined in  UnityAppController.h)

When launching the application (e.g. in applicationDidFinishLaunchingWithOptions) Unity creates an UIWindow and presents a splashscreen. Then it starts the initialization of the real unity-engine asynchronosly (with delay 0 on the mainthread). This means that if you want to do anything AFTER the unityview is loaded (f.e. put it as a subview into your own application) you dont want to put code into applicationDidFinishLaunchingWithOptions. You better override startUnity:

-(void) startUnity:(UIApplication*) application {
[super startUnity:application];
//anything that should be done AFTER the unity viewhierachy is loaded. like replacing the rootviewcontroller with your own.
}

Because thats the method called asynchronously. So in [super startUnity:] the UnityAppController  creates the Unityview and ViewController. Then the Unity-ViewController is set as rootviewcontroller in the window and the unityview added as subview to the window. Therefore it doesnt help if you change these things before startUnity is done.

If you add the Unity-Viewcontroller as subviewcontroller within your own Hierachy you only have to set the transform of its view back to the identity. Unity adds the view directly as subview of the window and therefore sets the transform to reflect the rotation of the app.

If you want to change the size of the unityview (Unity always asumes to be shown fullscreen) you need UnityRequestRenderingResolution. This function (yes, a c-style function) is defined in UnityInterface.h Just call it with the new dimensions, resize the view and call setNeedsLayout on it.

Once you added the Unityviewcontroller (received by either taking the rootviewController from UnityAppController) as a child to your own UIViewController, you can easily add any native interface on top of unity. And with UnityRequestRenderingResolution you can furthermore use the unityview as a non-fullscreen subview within your layout.

If you have any further questions or problems, just leave a comment.

13 thoughts on “Integrating Unity into a native iOS App”

  1. Did this actually work for you? I want to do something similar, but a good amount of posts around the internet claim that it is not possible at all. I am in fact having some trouble replicating your process…
    Think you could share an example file for us?

    Thanks!

    1. Yes, this did work for us. With the update to Unity 5 the integration changed a bit, but basically it just became easier. Where exactly are you experiencing problems?

  2. Basically the code Unity 4.6.1 is generating on my end does not really match with the startUnity part described here , and I am not sure about how to get that done.

    Anyway, I am very unexperienced with obj-c to properly implement something like this, so I might just try a different approach.

    In any case, thanks for your help!

    1. Actually i cant tell you 100% if it was different in 4.6.2 because we switched directly from 4.5.3 to 5. But i just looked into the Code of 4.5.3 and there the generated UnityAppController class definitly has the
      -(void) startUnity:(UIApplication*) application
      method. So if your own App Delegate subclasses the generated UnityAppController, it should work as described.

      What does your generated UnityAppController class look like? What problems are you facing exactly, maybe i can be of help.

      In general: if you are just starting, you may consider switching directly to Unity 5. Because with il2cpp they changed alot regarding how you send data to unity. And newer is always better 😉 And its free 😀

  3. I want add the Unity-Viewcontroller as subviewcontroller within my own Hierachy . But I’m not very clear about “you only have to set the transform of its view back to the identity. Unity adds the view directly as subview of the window and therefore sets the transform to reflect the rotation of the app.” could you show an example for us. Thank you very much

    1. I played a bit with the new integration in Unity 5, and its no longer necessary to set the transform to the identiy. Just add the ViewController you get from Unity as a subviewcontroller in your own hierachy and you are fine.

      If that doesnt help, just leave a comment .

  4. Hello, so two things:

    First, I don’t quite get the following:

    “If you add the Unity-Viewcontroller as subviewcontroller within your own Hierachy you only have to set the transform of its view back to the identity. Unity adds the view directly as subview of the window and therefore sets the transform to reflect the rotation of the app.”

    When I add my views on the StartUnity part of the class it crashes. So I opted for add the views inside the (void)willStartWithViewController:(UIViewController*)controller , everything goes smooth there. My view loads and the app works. Then, I have a button to start the UnityView (the AR). I add the following to the method after pushing the button:

    UnityRequestRenderingResolution(GetAppController().rootView.frame.size.width, self.view.frame.size.height);

    // This adds the UnityView finally
    [self.theView addSubview:(UIView*)GetAppController().unityView];
    [self.theView setNeedsLayout];

    (as the tutorial also posted around here) Next thing you know, the unityView loads but the screen is BLACK. Is you get an AR marker nearby you can see the 3D animations but NO camera view.

    //////

    I know this might be a lot to ask but, is it possible to share the source code?

    Any suggestions about what I explained?

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *