$NEWTON64 :: {blog|games}
 
Unity and the Android API

WARNING: This is a rather technical post about something completely different and not at all about Red Rover.

Several Ludum Dares ago, I made a game called Oases about seeking refuge from wifi hotspots in the environment. I built this on a Windows PC (my laptop), since it seemed the quickest way for me to bang out the network code in 48 hours.

Surprisingly, it turns out that it’s not all that easy to run around town escaping wifi hotspots while holding a laptop with an old and dying battery.

Cue the rise of mobile, wifi-enabled devices, however, and things get interesting. I’m an Android man myself, and since I’m slowly coming to terms with Unity, I started some tests in getting the latter to call functions from the Android API.

It was not straightforward.

The tutorial on Unity’s site gave a number of techniques for calling Android’s basic Java functionality from within Unity’s C# context, through JNI and C/C++. Unfortunately, even after reading it through multiple times, I still felt that, while it gave a lot of background information, it wasn’t as prescriptive as I was hoping.

Long story short: after patching that tutorial together with several dozen desperate and increasingly-confused online searches, I managed to gain access, in Unity, to the information polled from my Android device’s wifi manager.

I present those steps here for truth, justice, and the American whey. Hope it’s useful, and do call me out on the inevitable errors.

Calling the Android API from a Unity application
  1. Download and install the Android SDK. Learn it, love it.
  2. Start the Android SDK Manager, and install the SDKs you want. Make sure to also install the Android Support Library listed in “Extras.”
  3. Download and install the Android NDK. Love it, learn it.
  4. In my own setup, I’ve got the above installed at C:\Android\android-sdk-(version) and C:\Android\android-ndk. Short paths simplify things. I’ll be referring to them as ${ANDROID_SDK} and ${ANDROID_NDK}, respectively (Oh, and your Unity installation is probably something like “C:\Program Files\Unity”, to which I will refer as ${UNITY}).
  5. Download and install Eclipse; make sure to get the C/C++ variant.
  6. Start Eclipse, and install the Android Eclipse plugin as per these instructions.
  7. Create your Android library; these are the Java functions running on the Android API side of things, returning device status &c. to…”the ether” (essentially, back to Unity). In my case, these are the functions accessing the device’s wifi state. In Eclipse, go to New -> Project… -> Android Application Project.
  8. Give the app a name (what your device will visibly call it — not really important to us), a project name (for use in Eclipse’s workspace), and an Android package name (see those notes on nomenclature). MAKE SURE TO CHECK “Mark this project as a library.”. I forgot this once, and couldn’t figure out why Eclipse wasn’t compiling a .jar library for me.
  9. Leave everything else as is and continue; accept whatever clipart is shown, create a blank activity, and finish the wizard.
  10. Navigate your computer to ${UNITY}\Editor\Data\PlaybackEngines\androidplayer\bin. You’ll find classes.jar — a Unity-to-Java helper package from the Unity folks themselves — which you should copy to your Eclipse project’s libs/ directory (that directory was created automatically with your Android project in Eclipse, and should be visible in the hierarchy on the left).
  11. In Eclipse, go to Properties -> Java Build Path -> Libraries, and add classes.jar to your library path.
  12. Eclipse generated some code for your Android activity. How very kind of it. It’s called something like ProjectActivity.java. We’ll have to make some changes though; most importantly, we no longer extend the Android “Activity” class — but we do pass in an Android context. I have reasons. In your auto-generated MainActivity.java source code (you may have, and still can, rename it as you like), you can have the following (with these particular members specific only to my endeavour):

    public class MainActivity { // does not “extend” anything

      private Context m_context;
      private WifiManager m_wifiMgr;
     
      // ———————————————————- CONSTRUCTORS
      public MainActivity(Context c) {
        m_context = c;
        m_wifiMgr = (WifiManager)m_context.getSystemService(Context.WIFI_SERVICE);
        return;
      }
     
      // ————————————————————— METHODS
      public boolean isWifiEnabled() {
        return m_wifiMgr.isWifiEnabled();
      }
    }

  13. As you can see, I need the general Android context, if I am going to have access to the WifiManager class. The same is probably true for a lot of Android’s *Manager classes.
  14. In Eclipse, make sure Project -> Build Automatically is checked. If so, you should have a ProjectName.jar file in your bin/ folder (again, this folder is auto-generated).
  15. In Eclipse, in your file hierarchy, make a folder called jni/ (it should be the same level as bin/, libs/, res/, &c.)
  16. Create a .cpp file in there. Call it anything you like; ProjectCppBridge.cpp is an option, as is Sheila.cpp.
  17. You’ll also need an Android.mk file in the same directory, and maybe (but probably not) an Application.mk file. I’ll admit my Android-Fu is a bit weak, so start your learning process here. Why not. My own Android.mk looks as follows:

    include $(CLEAR_VARS)
     
    # override strip command to strip all symbols from output library; no need to ship with those..
    # cmd-strip = $(TOOLCHAIN_PREFIX)strip $1
     
    LOCAL_ARM_MODE := arm
    LOCAL_PATH := $(NDK_PROJECT_PATH)
    LOCAL_MODULE := libjavabridge
    LOCAL_CFLAGS := -Werror
    LOCAL_SRC_FILES := jni/YOUR_FILENAME_HERE.cpp
    LOCAL_LDLIBS := -llog
     
    include $(BUILD_SHARED_LIBRARY)

    And Application.mk:

    APP_OPTIM := release
    APP_ABI := armeabi
    APP_PLATFORM := android-8
    APP_BUILD_SCRIPT := jni/Android.mk

  18. Now, the actual .cpp file, where you write all your JNI code, is going to be a bit complicated, so I’m going to just include it wholesale here.
  19. A few things to note. The JNI_OnLoad() function is called automatically; just use it to initialise things. Here, I get the running instance of Unity, find Unity’s hook to the running application/activity, and use that as a context to pass to the MainActivity class (which, as shown above, requires a Context argument in its constructor).
  20. I also define a function, _cppbridge_isWifiEnabled(). This function is called from Unity, and then passes the call along to the Android API, and then returns a value back to Unity. Important to keep track of where all these calls are going, and to make sure all the names are referring to the right things.
  21. Download and install Cygwin. You don’t need any specific packages, just the command-line interface. You do need ‘make,’ so make sure that you search for it in the list of packages and install it.
  22. Open Cygwin and navigate (“cd /cygdrive/c/Eclipse/workspace/…”) to your Eclipse project directory (i.e., one above jni/).
  23. In Cygwin, run “${ANDROID_NDK}/ndk-build” (with the appropriate path typed in). This creates libs/armeabi/projectname.so in your Eclipse project directory.
  24. Now, finally, create your Unity project.
  25. In the Unity project’s Assets/ folder, create a directory called Plugins/, and within Plugins/ create another directory called Android/.
  26. Copy ProjectName.jar (from your Eclipse project’s bin/ directory) and projectname.so (from the libs/armeabi/ directory) into your new Assets/Plugins/Android/ directory.
  27. Copy ${UNITY}\Editor\Data\PlaybackEngines\androidplayer\AndroidManifest.xml into the same Assets/Plugins/Android/ directory.
  28. In the Unity script where you want to access the Android API, you must declare the following private references for every function you defined in your .cpp file:

    [DllImport("your_lib_name")]
    private static extern bool _cppbridge_isWifiEnabled();

    Note that “your_lib_name” is the name of the LOCAL_MODULE variable in your Android.mk file, without the “lib” prefix; or, it’s the name of the .so file you generated with ndk-build, but without the “lib” prefix or “.so” suffix. Also, the extern reference refers to the exact name of the C/C++ function we defined in our .cpp file.

  29. God, this blog.
  30. In Unity, go to File -> Build Settings…, and build your app for Android. You will end up with a .apk file, which you can then transfer to your device for installation and testing.
  31. A great way to debug your app is to fire up the DDMS. Plug your Android device into your PC via USB; open up a terminal (in Windows: Win-R, then type “cmd”); change to your ${ANDROID_SDK}/tools directory, and run ddms.bat; you should see a running list of all messages coming from your device. You can filter these in a number of ways: for instance, I prefaced all my error messages with “bagel,” so I could just search for that string. Look at the __android_log_print() function in the .cpp file provided above to learn more about printing debug messages.

Right. I think that’s just about complete, but feel free to give me a shout if something is missing/unclear/incorrect.

Now excuse me whilst I go rest my eyesies.

Blinking Totoro animated gif

Until Tomorrow

Today was my last day of gainful employment at the Royal Victoria Hospital.

SPOILER: I’m going to receive money to make video games.

Now, the middle bits, as efficiently as possible.

RVH building

I’ve been interested in game design for at least two years, and in fact that’s what’s driven me (with some meandering, I’ll admit) through Computer Science degrees at Concordia and then McGill. When I started on the latter, I began looking for a means to withstand the notoriously exorbitant Quebec tuition fees; as luck would have it, a friend suggested a contact of his at the on-campus Genome Centre who might be hiring; that contact (who’d actually been more interested in full-time bioinformatics graduates) then referred me to the Cardiovascular Research Laboratories at the RVH. Given that it was across the street from school, and that the work was straightforward (grokking & awk’ing data, adminning some sys), I took the job.

The work was good, and offered plenty of spare time for other activities, but I’ve come to realise that, ultimately, multitasking may not be my thing. I can’t work and listen to a podcast; I can’t read two books at the same time; I can’t sneeze and keep my eyes open; and I…found it difficult to work one full-time job, and then come home to another. My gig at the RVH was temporary — I knew it, my boss knew it, though the janitor may have been unaware — and it was becoming more and more obvious that the time had come. I resigned last month.

I am survived by many excellent and genuine people, doing genuinely excellent work on the genetics of cardiovascular disease. They have been, in a word, fantastic. Or wonderful, or amazing. One of those will do. My thanks and a raised glass to them:

Here’s to five and a half years. It…does not feel like five and a half years, here.

Of course, that much time under one (occasionally water- or asbestos-shedding) roof comes with its share of nav beacons: I started this website only a month or two before getting the job; I traveled from Edinburgh to Istanbul; I became both a Master and a hipster; I…well, the heartbreak or two; I got together with friends who make games; I attended my first GDC; and I can happily say that I am, for the moment, the one and only Rudzicz with an article in the New England Journal of Medicine.

not-bad.jpg, as the kids say and the crow flies.

Up next is video games. A friend found himself an angel, and with a little bit of bootstrap funding, we’re hoping to start something worthwhile: a number of ideas suggest themselves, including a little pet project of mine. I’ll write more about that when we have something a bit more tangible to show — though anyone who knows me will, I imagine, know exactly what I’m talking about. Mars awaits.

To my (now ex-)coworkers: live long and prosper. To all: I shall attempt to make this new endeavour a worthy one indeed. As my friend Lando would say: here goes nothing.

Please rise for the Canadian hymn to the Patron Saint of Lonely Wanderers.

Cheers. &c.

Red Rover — A new video!

Huzzah! Work’s been picking up on Red Rover — case in point: I finally got the CDLOD algorithm working in OGRE, and with a spherical object! The sphere is Mars! Ignoring oblateness!

The results are very preliminary, but it’s the kind of black triangle that gives me the warm fuzzies. Given my boundless felicity, I decided to forego the usual Screenshot Saturday, and instead favour a Movie Monday. Why not, Zoidberg?

Video embedded below. Possibly available in HD? Who knows. Internets are hard.

Astute readers (read: the three of you who’ve been here longer than two weeks) may note that this is the very first video update since my prelude/announce video, from August 2009.

Yes. Yes we’re really moving now.

i played Proteus.

i played Proteus.

it was my childhood, twenty-four years young.

it was lonely.

it was warm.

it was like massaging my ears with breasts.

i chased a raincloud.

i saw the moon set in an ocean.

i found islands within islands.

i wondered at the falling snow.

i played Proteus.

you should play Proteus.

My Holiday Playlist

The holidays may be over, but that doesn’t mean the holidays are over! Wait hang on, that doesn’t even!

This latest holiday season was a resounding success, filled (as expected) with relaxation, family and friends, and the consumption of various foodstuffs, ethanols, and multimedia products. I thought I’d take a few paragraphs to exercise my vocabulary and look back at some of the games tiding me over between foodbabies.

MINERVA: Metastasis (PC)

Minerva Title Screen

Ah, Newfoundland.

My friend and Mount Royal Game Society co-organiser Stephen suggested I take a look at this Half-Life 2 mod, marketing it to me as (paraphrasing) “an exploration of a more fully-realised space than the constantly advancing roller-coaster of HL2.” It was interesting to note the process of familiarisation within the facility, learning the architecture and eventually improvising and using it to my advantage in firefights. On the other hand, a few areas do feel a bit arbitrarily designed (or, don’t seem to make architectural “sense”), simply to provide certain encounter types: e.g., long, tight hallways, or an emphasis on z-axis fighting. And, on the larger scale, it did sometimes feel like a repetitious cycle of Exploration-Stockroom-Encounter, Exploration-Stockroom-Encounter, of the type that Valve (as I recall) cleverly managed to avoid in HL2.

That said, another interesting aspect of the game is the player’s dependence on the character of Minerva. She (it?) is manifested as nothing but the occasional text message—varying in tone from concerned to hostile to dispassionate—but, since she’s the one giving motivation and context to the mission, she develops something like a caregiver’s presence. More than once, I found myself hoping for her reassurance or guidance so that I wouldn’t have to proceed “blindly.” And all that simply from a smattering of scripted text.
 

Hotel Dusk: Room 215 (DS)

Hotel Dusk: Room 215

Mirrors on the ceiling, pink champagne on ice.
And she said: “We are all just prisoners here, of our own device.”

I actually got game this as a Christmas gift, since it was on my oh-so-handy Amazon.ca wish list. Obviously, points for style and originality on this one: it’s a film noir game, on a DS that you hold like a book, set in late-1970′s California. I’ve really only just started out, but the characters have already made an impression, and the narrative has introduced a number of unknowns and mysterious coincidences that really capture the feel of the older film noir movies.

Hotel Dusk makes use of the adventure gaming trope of discrete time blocks, similar to The Colonel’s Bequest or the Gabriel Knight series: that is, the player solves a few puzzles and witnesses certain events within, say, fifteen minutes of game-world time, before advancing to the next time block or chapter. I know opinions will vary, but I really dig this format. Despite the arbitrariness of the time blocks—one “half-hour” block of game time might take several hours or just ten minutes to play—I’ve always felt that they lend a kind of pacing and a sense of progress, almost desperation, as the storyline races against the clock. This can obviously work against a given game, but so far Hotel Dusk pulls it off well. My only complaint is that there are only one or two very specific puzzles/dialogues that occur in each time block, so the game ends up feeling mostly linear. Regardless, the story and setting are definitely compelling enough to keep me playing more for now.
 

Minecraft (PC)

My Minecraft House

No Admittance Except on Party Business

Maybe you’ve heard of Minecraft. It’s sort of popular now.

I first played it way, way back, around when it first popped up online—this was while researching existing games with procedural content generation, and before the recent Minecraft-mania. (Oh, bugger, did I just say I played Minecraft before it was cool?) I thought the landscapes were pretty interesting, though I didn’t think much of it as a game, per se. Fast-forward a few months, and notch was suddenly contemplating how to avoid papercuts while sleeping on piles of cash; Minecraft-mania had finally hit. Figuring I must have missed something, I paid for the stand-alone alpha and gave it a second chance.

Once again, I just didn’t get it. Obviously, creations like the Enterprise D or a working logic unit were impressive, and player-generated stories/adventures/mishaps (such as the Great Fire of Minecraft) were fantastic (and usually tragic), but for the life of me I couldn’t stay interested beyond the point of making my first torch and digging deep enough to need the latter. My interest waned once more, until finally, during the holidays, I decided that perhaps the third time would be the charm, and fired it up again. This time, I’ll admit I played a bit longer: my spawn point was on an island, and I resolved to dig myself the equivalent of the Chunnel to connect to the mainland. But once that was finished (read: when the tunnel accidentally flooded), I was again left standing (swimming) with nothing to do. It was at that moment, I believe, that it hit me.

I claim that Minecraft is a toy, not a game. My friend Matthew was elegant and concise: “There are no explicit goals or directives, just a wonderful sandbox of pure undirected play” (emphasis mine). There is nothing in Minecraft beyond what the players make for themselves, literally and figuratively. It’s a formula that clearly resonated with a lot of people, and it’s probably a revolutionary step (that is, the most recent and most successful) in the exploration of agency and game-like systems, but I don’t connect with it. When I was younger and played with Lego, I’d make the object as per instructions, and to hell with the “suggested variations” on the back of the box. I suppose I’ve always just been more interested in having a clear direction and purpose—even if I occasionally veer away from it. Compare and contrast Minecraft with Dwarf Fortress: in the latter, the geographical and political history, as well as the individual dwarfish personalities, gives me a much greater sense of context and motivation than I ever found in Minecraft, and I can therefore enjoy DF much more thoroughly (modulo their respective interfaces).

My full and sincerest respect goes to @notch: here is an individual who, in a few months, managed to single-handedly put together a project that laid bare the essence of play (creativity and uncertainty in equal parts) and provide a wonderfully meaningful experience for many thousands of people; and all this while making himself a tidy fortune. He is the embodiment of the indie game developer’s dream. But I can say right here, and with absolute certainty, that I’m just not that interested in Minecraft.

There.
 

Serious Sam: The First Encounter (HD) (PC)

Headless Kamikaze dude

The headcrabs (ironically?) of the Serious Sam universe. So much fun and/or terror.

Right, so, opposite end of the spectrum. Minecraft allows the player to do just about anything; Serious Sam, on the other hand, merely allows them to run, dodge, or shoot, relentlessly. It’s the Army of Darkness of video games: mindless fun from the “Does this make sense? Do we give a fuck?” school of design. And it was part of Steam‘s holiday sale.

I’d always been interested in Serious Sam, as it seemed to tap into that sweet spot of speed and mastery that contributed to Doom‘s original success. So far, I’m loving every minute of it. It’s unabashedly tongue-in-cheek (the saviour of the universe wears Chuck T’s, for Darwin’s sake), and yet it makes rather smart use of its variety of guns and enemies: I find myself reacting to each encounter and switching between weapons way more often here than in most other FPS’s.

I’m not sure how long they’ll be able to prolong this adrenaline rush, but for right now, it’s just a lot of fun. Full stop.

 

Boxing (Atari 2600)

Boxing gameplay

Ali vs. Liston (May 25, 1965)

The weekend before the holidays ended, I had some friends over for sushi and media. While I’d planned for movie-watching, we ended up blitzing through my collection of 80+ Atari 2600 games instead, and without a doubt, Activision’s Boxing was the highlight of the night.

The game has comparatively better graphics than most 2600 games, but it’s still extraordinarily minimal (as I pointed out, it looks a lot more like two spiders mating). Given the one-button input from the Atari controllers, it’s rather minimal in terms of interaction as well. And yet…

A successful punch (a shot to the face) at arm’s length lands an attacking player one point, while a punch from in-close gives two points. Two players can face off against each other, or one player can face the CPU, and full games last only two minutes, or until one player achieves a KO (100 points landed on the other boxer). What makes the game special, however, is the reaction to a successful punch: if a player lands a hit with their right hand, the other boxer is pushed towards their waiting left hand and vice versa, creating what a friend mentioned must be one of the first combo systems ever implemented in fighting games. When being attacked with a combo, a player has to try to back away from the attacker, or hope that the latter’s timing is off and the salvo ends naturally; if the defender is up against the ropes, there’s nothing to do but pray the other player’s thumb gets tired. The result is a ruthless and thrilling and almost chess-like strategic battle for domination of the centre of the ring.

Videos don’t do it justice. With an extremely limited set of rules (1. Points for punches at different ranges. 2. A single round with a time and point limit. 3. “Physical” reactions to punches.), Boxing creates what is probably the most distilled and accurate representation of the sport possible. Players grapple, weave, get frustrated, charge, rest; thumb fatigue becomes an actual physical factor; sudden reversals literally bring people to their feet. In fact, the more I think about it, the more I can convince myself that this is the only boxing simulation we ever really needed; the rest are just fluff.

We were bent over laughing and cheering with this game. And I landed something like a 30-hit combo on the computer, for the fastest KO among us. The whole thing was magical.
 

Back to the salt mines

The holidays are now over, and it’s back to the regular weekday grind. But I like to think I made the most of my gaming opportunities in the meantime.

How about you? What games brought you all through the new year?