Sandbox Unity app in an existing iOS app

I HAVE CREATED A NEW WAY TO INTEGRATE UNITY WITHIN AN EXISTING IOS APP. YOU CAN FIND THE POST HERE.

The problem

After my previous blog post on how to sandbox an iOS app inside of a Unity project, I got some questions on how to do the same but put Unity inside of an existing iOS app.

After playing around with it, I found a solution which works well for me to add Unity app in an existing iOS app.

The solution to add Unity app in an existing iOS app

First I’ll create a simple Unity3D project which just shows an square on the stage.

Unity app in an existing iOS app
Create a simple Unity3D project

 

Now you’ll need to create the entry point for your custom code. You can do this by creating a folder Plugins in the Assets folder. Inside the Plugins folder you create a folder iOS and inside that folder you create a file TNAppController.mm (or whatever name you like).

Put the following code in this file.

Save the project to a folder, mine is /PROJECTS/StandaloneUnity/unity/UnityPart. After you’ve done this, build the project for iOS by pressing ⌘ + shift + b. Choose the iOS platform and set the build settings to whatever you like.  Hit ‘Build’ (if you haven’t saved your scene yet, don’t forget to save it first and then add the scene in the Build settings window). I’ve save the build under /PROJECTS/StandaloneUnity/unity/ios-build/UnityStandAloneIOSBuild.

Unity app in an existing iOS app
Add the scene to the build and provide the correct settings for your iOS app

Now we can create the iOS project in which you want to add the Unity iOS build.  Go to Xcode and create a new project.  Choose for the ’empty application’ template and save the project. My location is /PROJECTS/StandaloneUnity/ios/UnityStandAlone, so my directory structure in the end looks like this.

  • StandaloneUnity
    • ios
      • UnityStandAlone
    • unity
      • ios-build
      • UnityPart

Alright, now we can link up both projects.

Go to the ios project which has been generated by Unity and look for the folders ‘Classes’ and ‘Libraries’ and drag these to your own Xcode project.  Make sure to uncheck ‘Copy items into destination group’s folder’ and select ‘Create groups for any added folders’. Make sure you add the files to your target.

Unity app in an existing iOS app
Drag the folders to your Xcode project
Unity app in an existing iOS app
Settings for importing

Now we need to adjust the ‘Header search paths’ and the ‘Library search paths’ values in our project’s Build Settings.  If you want to share this project with other team members, the best thing to do is work with relative paths by using the ${SOURCE_ROOT} keyword.  This keyword will resolve the path to the directory where your project file is in

In my case the value for ‘Header search paths’ will be “${SOURCE_ROOT}/../../unity/ios-build/UnityStandAloneIOSBuild/Classes”.

The path for ‘Library search paths’ will be “${SOURCE_ROOT}/../../unity/ios-build/UnityStandAloneIOSBuild/Libraries”

If you try to build your project, you’ll get a ton of warnings. This is because the generated code from Unity is not written in ARC. So we’ll have to tell the compiler that these files don’t use ARC.  We can do this in ‘Build phases > Compile sources’ and give those files the ‘-fno-objc-arc’ flag (there are quite a few … but you only need to do this once, so bear with me).

These are the ones I flagged:

  • VideoViewController.mm
  • UnityViewControllerBase.mm
  • ScriptIntegration.mm
  • DisplayManager.mm
  • WWWConnection.mm
  • iAD.mm
  • DeviceSettings.mm
  • CVTextureCache.mm
  • GlesHelper.mm
  • Keyboard.mm
  • UnityAppController.mm
  • UnityAppController+Rendering.mm
  • SplashScreen.mm
  • AppDelegateListener.mm
  • iAD_Scripting.mm
  • RegisterClasses.ccp
  • iPhone_Sensors.mm
  • UnityAppController+ViewHandling.mm
  • LifeCycleListener.mm
  • UnityView.mm
  • CrashReporter.mm
  • CMVideoSampling.mm
  • RegisterMonoModules.ccp
  • EAGLContextHelper.mm
  • iPhone_Profiles.ccp
  • iPhone_OrientationSupport.mm
  • ActivityIndicator.mm
  • VideoPlayer.mm
  • RenderPluginDelegate.mm

If you now rebuild the project, you shouldn’t see the a lot of errors anymore (only a few ).

Remove the main.mm file from the Classes folder and rename the main.m file to main.mm in ‘Supporting Files’.  Overwrite the contents of this file with the following.

Now we need to add some imports to the precompiled header file of our project (the .pch file in ‘Supporting Files’.  Go to the group ‘Unity/Classes’ and find the .pch file there (probably it will be named something like ‘iPhone_target_Prefix.pch’ and copy its contents to the .pch file in you ‘Supporting Files’ group.

Now we’ll need to add a ‘Run script’ to our Build Phases.  Click on the little + sign at the top left corner when you are in the Build Phases tab and choose for ‘New run script build phase’ and drag it after ‘Target Dependencies’.  Now add the following script inside it.  Don’t forget to set the correct directory for your project :-)!

Unity app in an existing iOS app
Run script

Alright, next up is adding the right libraries. Add these:

  • Foundation.framework
  • UIKit.framework
  • OpenGLES.framework
  • QuartzCore.framework
  • OpenAL.framework
  • libiconv.2.dylib
  • libiPhone-lib.a
  • AudioToolbox.framework
  • CFNetwork.framework
  • MediaPlayer.framework
  • CoreLocation.framework
  • SystemConfiguration.framework
  • iAd.framework (set status to optional)
  • CoreMedia.framework
  • CoreVideo.framework
  • AVFoundation.framework (set status to optional)
  • CoreGraphics.framework
  • CoreMotion.framework (set status to optional)
  • GameKit.framework (set status to optional)

We are almost there. Only need to update a few more Build Settings.

Set the ‘Architectures’ to ‘armv7’

If you debug the app, you’ll see it will compile very slowly because of the dSYM file being generated, you can turn this off by setting ‘Debug information format’ for debug to ‘DWARF’ instead of ‘DWARF with dSYM file’.

At ‘other linker flags’ add the following values

  • -weak_framework
  • CoreMotion
  • -weak-lSystem

At ‘other c flags’ add ‘-mno-thumb’ value.

At ‘c++ language dialect’, select ‘compiler default’.

At ‘c++ standard library’, select ‘libstdc++ (GNU c++ standard library)’

And let’s also add 2 of our own by pressing the little + sign at the top left ‘Add User-Defined Setting’.

Key GCC_THUMB_SUPPORT value NO
Key GCC_USE_INDIRECT_FUNCTION_CALLS value NO

Alright … that should be it. Hook up an iOS device to your system, select it at the top left in Xcode and hit Build.  Normally if everything goes well, the application should compile. (you will get errors if you try to build with a simulator selected, this only works on a real device!) And you will see the following result.

Unity app in an existing iOS app
Compile and run the app

This is the code that gets executed from the TNAppController.mm file.  So that’s your entry point to add the rest of your application.

To show the Unity content you’ll need to create a new class TNUnityViewController for example and let it extend UnityDefaultViewController.  Rename the .m file to .mm.

Then add the following code to the .mm file.

Now present this view controller and you will see the contents of what you’ve created in Unity.  You also should add the -fno-objc-arc flag on this file as well!

Hope this helps some of you guys out to sandbox an Unity app in an existing iOS app!  If you have any questions, just put them in the comments!  I can’t upload the code to github because there is a 100MB limit per file and some of the unity generated files are +100MB, but if you contact me via email I can send them to you if you like!