An in-depth story on how I handled a technical problem with tight time constraints. If you don’t understand what’s going on, don’t worry, neither did I.
At my first hackathon, Lumohacks 2018, my friends and I had a goal of creating something meaningful while learning along the way. These competitions are a great opportunity to do all that in a short period of time (this was a 24 hour hack), so we decided to create a virtual reality psychotherapy app with Unity. We were complete rookies, and for my buddies, this was their first time programming a project outside of the classroom. With near zero expectations, we downloaded the SDK and set off on our adventure. Things started off a little slow because we spent the first few hours watching Unity tutorials on YouTube. However, things picked up as we got a grasp of the concepts and let our creativity flow. About 18 hours into the hackathon, the main VR parts of our project were finalized.
You’ve probably played or seen a game made with Unity before (ie. Overcooked).
However, things took a turn when we wasted hours creating an unintuitive and unusable VR menu. The idea of the project was to use cutting edge technology to increase accessibility of psychotherapy treatment, but there was nothing accessible about this menu. We were running out of time and didn’t want to spend more of it watching tutorials.
Luckily, an idea popped in my head.
Unity has a feature that allows exporting projects into a native codebase. This in turn allows developers to import the code into the platform’s native IDE. Being a novice Android developer at the time, that meant that I could continue development with Android Studio. What if I just made an Android menu that launched the Unity engine with the press of a button? Having to simultaneously learn Unity and implement our ideas was rewarding but limiting. Moving the remaining development into Android Studio was going to help us finish our project on time, but only if it was possible. However, I wasn’t an expert in Android development, so I wasn’t completely confident in my idea. The burnout was really getting to me and I needed a break. Luckily, one great thing about hackathons is that there’s usually a ton of free stuff given out, so I spent an hour throwing a bouncy ball against the wall. As the drowsiness began to wear off, I thought the idea over one more time. We had nothing to lose, maybe except for the competition, so why not?
I exported the Unity project and opened it in Android Studio. As expected, it took me a while to get everything loaded properly. This had me doubting myself again. There were a lot of old plugins and libraries that needed updating, so I was afraid of not being able to get it to build due to version discrepancies. I spent what seemed like an eternity resolving conflicts.
This is the type of stuff most developers hate to deal with. Before any real programming can be done, we have to set up the development environment. It’s like loving to cook and hating to clean the kitchen. Version discrepancy means that one part requires a specific version of something, but there’s a lot of parts and none of them want the same one. This can be a slippery slope because it’s very possible that there’s no common ground. That’s like hosting a party and you ask a friend to pick up some fried chicken along the way. Then they arrive with a whole rotisserie chicken. So close yet so far. Does that analogy make sense? I don’t know.
Then the unexpected happened: the app built successfully and launched on my phone. It worked! Awesome, now I have something to work with. I immediately looked at the AndroidManifest.xml:
<activity android:label="@string/app_name" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:hardwareAccelerated="false" android:name="com.adinkwok.vremdr_unity.UnityPlayerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
<category android:name="com.google.intent.category.CARDBOARD" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
This is where developers define a roadmap of specific information about the app.
Awesomely enough, reading that code allowed me to check off my main assumptions. The Unity engine is loaded in the form of UnityPlayerActivity, which is immediately launched at the start of the app. So, all I had to do was create a menu that replaces UnityPlayerActivity as the starting Activity, then launch Unity at the press of a button.
In Android development, an Activity is what users might see as an app screen (for example, the home page and settings screen could be two separate Activities). You can launch an Activity by having it as the very first screen you see or program it to launch on an event or action (ie. on button press).
// Code snippet to launch the UnityPlayerActivity manually
Intent startSession = new Intent(this, UnityPlayerActivity.class);
startActivity(startSession); // Kotlin > Java
From here on out, it was just simple Android development. I started by creating my MenuActivity. The first thing I made was a START SESSION button, which I programmed to launch the UnityPlayerActivity with the code shown above. Then I added a non-functional (“proof-of-concept”) settings button and a button that opened a browser to our HTML5 UP website (I may or may not still own eemdr.tech). Now that we had an intuitive menu with our auto-generated logo and a lot of green, it was decently presentable — but did it work? Yes it did, and we were able to go to sleep with three hours left before the submission deadline.
The project was a success! So much so that we made it to the finals and placed second over 80 teams. Not bad for a group of first time hackers. Among the sunshine and fireworks of being finalists, there are still things I’m looking to improve. One area of improvement I noted comes from the realization that I could have acted more efficiently when we ran into the predicament with the horrible VR menu. To be fair, I was feeling burnt out, but I could have been more confident in trusting myself to execute the idea of native layout development. I tend to second guess myself more often than I should, and although exercising caution is a safe strategy, situations with tight time constraints may benefit more from acting first and asking for forgiveness later. Lastly, if you’re wondering what our menu looked like, I hope you didn’t have high hopes:
Thank you, come again.