Monday 5 August 2013

Android Maven with Unity3D & JNI

In my previous post I wrote about my experiment in adding Unity view as subview inside an existing simple android project... which worked well until I tried to do the same with a giant android project that utilises maven and uses multiple libraries.

As an iOS developer that was a new experience to me. And, to be honest, although I understand the idea behind maven I felt it was too much hustle for what it is and more over when it comes to android support in eclipse there is a long way to go to have easy to use solution. (I ended up using the command line instead of eclipse)

Anyway, after some trial and error (and a headache) I managed to have something that kind of work. I will share it here if it helps anyone who is trying to do something similar & also for my future reference :-) (using Unity 4.2 and a Mac OS X)

In this post we will refer to unity android project as generated project and the project we are trying to integrate into as targeted project.

Please note that what this post might work for one man band only, especially when it comes to maven related steps as I'm no expert in it (this is my first encounter with maven) and I did it just for experimenting with Unity:

1. Export your unity project as android project

I usually put the generated project in the same directory as the targeted project.

If you are using eclipse don't forget to do the steps mentioned in my previous post for generating a jar by ticking "Is Library" in the generated project properties and adding both the classes jar and generated jar to the targeted project properties->Java build path & Android library.

2. "Mavenize" Unity libs

By installing Unity jars and so libs from the generated project into your local maven repository so you can add them as dependency in your pom.xml file.

Starting with jars:

- untiy-classes.jar (You may notice that I spelled the classes jar as "untiy-classes.jar"... it is typo in unity generated project and hopefully they will notice it in future update :-) :
mvn install:install-file -Dfile=/PATH_TO_GENERATED_PROJ/libs/untiy-classes.jar -DgroupId=Unity3D  -DartifactId=Unity3D -Dversion=4.2.0 -Dpackaging=jar

- unityplayerproxyactivity.jar (generated when you tick the generated project as android library)
mvn install:install-file -Dfile=/PATH_TO_GENERATED_PROJ/bin/unityplayerproxyactivity.jar -DgroupId=UnityPlayerProxyActivity  -DartifactId=UnityPlayerProxyActivity -Dversion=1.0.0 -Dpackaging=jar

You can give any names and versions you want... preferably to use the actual numbers related to the engine and your project though.

Android maven plugin documentation mention that you can add also the native libs (so) in similar fashion although it didn't work for me for some reason

Instead I did an ant task to copy the so files (Unity4.2 generated project will have libmain.so libunity.so libmono.so inside libs/armeabi-v7a) to the target folder during the clean phase of maven (if anyone has better idea please shout it and share!) and I also copied the assets folder contents to the targeted project assets folder

Targetted project's pom.xml:
//inside dependencies tag:
<dependency>
 <groupId>Unity3D</groupId>
 <artifactId>Unity3D</artifactId>
 <version>4.2.0</version>
</dependency>
<dependency>
 <groupId>UnityPlayerProxyActivity</groupId>
 <artifactId>UnityPlayerProxyActivity</artifactId>
 <version>1.0.0</version>
</dependency>

// inside build plugins tag include an ant task
// this will copy so files and assets to the targeted project during
// clean phase of maven
<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-antrun-plugin</artifactId>
 <version>1.7</version>
 <executions>
  <execution>
  <id>ant-copy-so-assets</id>
  <phase>clean</phase>
  <configuration>
   <tasks>
    <echo message="***** copy unity assets and libs! *****" />
    <copy
    todir="${basedir}${file.separator}target${file.separator}classes${file.separator}lib${file.separator}armeabi-v7a${file.separator}">
     <fileset dir="PATH_TO_GENERATED_PROJ_SO_FILES" />
    </copy>
    <copy
    todir="${basedir}${file.separator}assets" overwrite="true">
     <fileset dir="PATH_TO_GENERATED_PROJ${file.separator}assets" />
    </copy>
   </tasks>
  </configuration>
  <goals>
   <goal>run</goal>
  </goals>
  </execution>
 </executions>
</plugin>

3. Follow the previous instructions for integrating Unity view (4 or 5)

4. Execute maven command to build to device
mvn clean package android:deploy android:run -Dandroid.device=usb
If everything is done correctly your android project should run in the device with unity view as well

5. Updating unity project
lets say you added new assets or new logic to your game/ view in Unity then you can simply export the new android project into the same location (overwrite) then execute maven command as in step 4 (no need to repeat steps 1- 3)

Well... that's all for now... although its still not a perfect workflow I hope it will help someone