Unity native Android and iOS integration

For the development of the Zermatt Skiguide App, my team and I implemented a hybrid solution. The core of the app was created natively with Android Studio and Xcode while the interactive 3D map of the ski area was developed with the help of Unity game engine.

Nija Nikolic
dreipol

--

Visit www.dreipol.ch to learn more about us.

The deciding factor was our previous experience with these tools. Native development offers the best control and performance in regards to the app – working with complex 3D scenes is a pain though. Unity*, on the other hand, has a mediocre UI system but an awesome 3D handling and the content created with the game engine can be compiled for multiple operating systems.

*It should be noted that our concept and decisions were made in 2015 when Unity’s UI system and the native 3D frameworks such as SceneKit were not yet as established as they are today.

NativeBridge.cs

To ensure the interaction between Unity and the native part, a bridge had to be built to control the communication with the 3D map. On the native side, functions in a C-based language had to be compiled into a library in order for Unity to access them. These native files (plugins) link their code directly to C# Unity with [DllImport()].

In Unity, the used native files to call from the NativeBridge.cs should be stored under Assets/Plugins/iOS.

ZERUnityBridge.h

ZerUnityBridge.mm

Exporting the 3D map into a native project

In order for the native app to access the 3D map, the Xcode or Android projects had to integrate the exported Unity files. This works as follows:

In Xcode, the generated Unity folder must be linked. This is done via reference to the folder or to the individual files. Once linked, they can easily be replaced when changes in the ski map are being made — please note that the file structure can change with newer Unity versions.

The next step is to patch the UnityApp controller. In doing so, the AppDelegate of the host application instead of the «normal» unity application UnityController gets called. For the automatic overwrite we use some shell lines inside Xcode:

Then we have to modify main.mm file in the classes folder by renaming the AppControllerClassName from «UnityAppController» to how the AppDelegate of the host application is called. In our case: «AppDelegate».

In Android Studio, the «Unity-Export»-folder can be placed in the project and the files can be moved to the correct folder using a ShellFile (.sh).

A problem we encountered with the Android version was, that the 3D map was showing the activity bar because we used the applicationContext first instead of the activity.

Multithreading with Unity

Another problem was that Unity calculated everything on the main thread. When native sends a large amount of data, the thread handling can cause the map and the rest of the UI to lag. For example, the native part sends a JSON string to update the 3D map: What slopes are open, closed, in preparation, weather data, restaurant information, lift highlighting, route color, etc.
With the help of a Unity thread plugin (we went for «Ninja Thread») the sync can now be executed in a coroutine.

Learning

The hybrid solution for the Zermatt Ski Guide App worked out and looked great but sometimes it caused trouble when a bug occurred and the team had to check the native development as well as the unity part and the customers' server data. You need good communication within the developer team in order to get things fixed quickly.

Sources and links

Zermatt Skiguide App

I hope you enjoyed reading and happy coding!

. . .

Feel free to like this post, share it, follow me or dreipol on Social Media:

twitter.com/nijanikolic
medium.com/@nija.nikolic
twitter.com/dreipol
www.dreipol.ch

--

--