December 2014

Volume 29 Number 12

Unity : Developing Your First Game with Unity and C#, Part 4

Adam Tuliper | December 2014

Welcome to the final article in my series on Unity game development. Remember when the app market was first exploding? Everyone was jumping on the bandwagon, and there was an app for everything. With a gazillion apps, though, came the trouble people had finding your app. Having apps get lost in the marketplace is a very real problem for developers. The Windows Store/Windows Phone Store isn’t the dominant marketplace on the planet. Does that mean you shouldn’t develop for it? Absolutely not. Developers have a real opportunity here to have their applications found. I hear of developers having their apps featured often. I know exactly three people who have had this happen on other platforms, and I talk to a lot of developers from all platforms.

In this article, I’ll look at the process of taking a game developed in Unity to Windows. The process is pretty straightforward and allows you to do some pretty cool platform integration that’s relatively easy to implement in a game. There’s some excellent tooling available as of Unity 4.5, which supports the new Universal Projects (solutions that generate packages for Windows Phone and Windows Store with shared code), as well.

As you work, keep this popular saying in mind, “Test early, test often.”  You’re not likely to hear a better software development mantra, and it holds very true in game dev. I’d like to revise it slightly, though: “Test early on devices, test often on devices.” No matter what the platform, you’ll find devices might act different than expected.

The Platform

If you’re reading this magazine, you likely have an idea of the Windows ecosystem. I’ll just do a quick review of what Unity supports in that ecosystem. You can target Xbox 360, Xbox ONE, Windows Phone 8/8.1, Windows 8/8.1 (Windows Store apps) and the desktop. You can choose all of these targets in the free version of Unity except Xbox. You’ll see Xbox listed in the build options, but you can’t build to it unless you’re in the ID program for Xbox ONE. For Xbox 360, you must sign up via an approved publisher. If you’re working on something super cool, please check out the ID program at xbox.com/Developers/id. Windows Phone and Windows Store have very similar build processes.

Remember, Windows Phone and Windows Store have the following build options: Windows Phone 8 via Silverlight; Windows Phone 8.1 via Silverlight or the Windows Runtime (WinRT); Windows 8; Windows 8.1; universal apps that target Windows Phone 8.1 and Windows 8.1.

Building for Windows

Making a build from Unity is actually quite simple. For local testing, it’s just a matter of bringing up the build dialog (File | Build Settings), clicking Build, and choosing an output folder. The Build and Run option launches your game after compilation on either a connected phone or your local system, depending on what you choose. That’s it at a basic level. After a successful build, the folder you chose will open with either an executable or a Visual Studio solution. Errors will be shown in the console window, so it’s always a good idea to have it open via the window menu. If you don’t have the console window open, you have to remember to look at the very bottom status bar of the Editor window for a single line of red messages. It’s a bit hidden, but once you know it’s there, you won’t forget it.

For All Builds Unity runs your build with what it calls a player and it supports the players of all the different platforms noted previously. When you create a build of your game, you’ll need to add every scene you want in the build. To load the various scenes in your game (outside of the first one, which loads by default), you use Application.LoadLevel, which takes either a scene name such as Application.LoadLevel(“Level1”) or an index such as Application.LoadLevel(2). I’m not a fan of using the index method because, as you’ll see, scene ordering can easily vary.

Every level you want to load in code must be added to your build. In the Build settings dialog, you add whatever scenes you want in the build via the “Add Current” button or by dragging and dropping scene files onto the build dialog. Here, you can reorder them, as well (which, again, makes loading scenes by index dangerous because they can easily get reordered). You can enable or disable these scenes for any build by checking or unchecking them. As Figure 1 shows, the steps are as follows:

  1. Add scenes to the build.
  2. Ensure the desired scenes are checked. I often check a test scene to include in a local build and uncheck it for the final build.
  3. Highlight the platform for which you want to build.
  4. Click Switch platform to trigger Unity to prepare your assets for the selected platform and enable platform-­specific preprocessor constants, such as UNITY_METRO, UNITY_IPHONE, UNITY_WEBPLAYER, and so forth.
  5. Build your game into a platform-specific package.

Adding Scenes to a Build
Figure 1 Adding Scenes to a Build

For Windows Desktop The standalone (desktop) build is the default when you open Unity. With this build, Unity uses Mono to compile your game assemblies and packages them with the runtime engine. You get an executable file and a folder into which everything is packaged. This build is straightforward, as are most desktop builds.

For Windows Store and Windows Phone This is where the fun begins, and I mean it. You can do some really cool platform integration when exporting to Windows Store and Windows Phone. You can use a live tile to entice users to come back to your game for free game credits, send a text message, use geofencing and more. The main thing to note is that it’s relatively easy to integrate platform-specific features into your game.

The build process differs a bit from the desktop build, although you can still do a quick Build and Run from the dialog and get a running Windows Store or Windows Phone app pretty quickly for testing.

To understand where platform-specific code can fit into your Unity game, look at how Unity compiles your code. The code that runs in the Unity Editor is compiled by the licensed version of Mono. This means you can’t make WinRT (Windows Store/Windows Phone 8.1) API calls like GeoLocation while running your game in the Editor, as there are specific WinRT methods that don’t exist in Mono. Likewise, there are features in Mono that don’t exist in the Windows Runtime, such as Hashtable and traditional .NET file access via System.IO. There are many overlaps between Mono and the Windows Runtime, but they’re different APIs, so expect some differences.

When you build your project for the Windows Store, Unity uses the Microsoft .NET Framework to compile the game assemblies. By default it uses the .NET Core to compile your assemblies, which is essentially what WinRT .NET is. You simply need a way to tell Unity to compile your platform-specific code only when compiling for that particular platform.

There are two main ways of using platform-specific code here. (There’s a third technique called a bridge, which wires up actions between Unity and Visual Studio solution code, but it’s used far less often and won’t be covered here.) The first technique is to use a plug-in. You can write your own, which is fairly trivial, or download one from several good sources. As of this writing, prime31.com plug-ins for Windows Store and Windows Phone are free. Virtually every major publisher using Unity uses plug-ins in its game projects. Get these while you can, it’s a pretty amazing deal.

Using Platform-Specific Code

Via Plug-Ins The plug-in model in Unity uses two versions of a library with the same method signatures. One is essentially a stub version of your library compiled against the .NET Framework 3.5, which is placed in Assets\Plugins\YourPlugin.dll. That’s the version Unity uses when your game is running in the Editor. The other one is compiled for the platform you’re targeting—say Windows Store or Windows Phone—and is packaged into your game when you create a build from Unity, as shown in Figure 2.

Building with Platform-Specific Code via a Plug-In
Figure 2 Building with Platform-Specific Code via a Plug-In

The platform-specific library is placed in Assets\Plugins\<Platform> \YourPlugin.dll (the platform can be Windows 8.x, iOS, Windows Phone 8 and so on).  If you have a reason to create one yourself as opposed to downloading one of the many already available, check out bit.ly/1EuLV1N for the basic directions. The primary difference in the plug-ins (outside of the platform API, of course) is where you put the platform-specific dll. You can find the plug-in locations at bit.ly/1v2ml1m.

Using one of the prime31 plug-ins here to set a live tile is as simple as attaching the code in Figure 3 to any GameObject in your scene. The SettingsPane and Tiles class are plug-ins that contain functionality to implement platform-specific code.

Figure 3 Prime31 Plug-in Code

public class WindowsStoreAppSettings : MonoBehaviour
{
  private void Start()
  {
#if UNITY_METRO // A preprocessor directive to run when Windows Store
                // build is selected in Unity.
  SettingsPane.registerSettingsCommand("Privacy Policy",
    "This is my privacy policy. Consider a url as well to bring you to the site.");
  // Set the live tile. You can set a source as an Internet URL, as well.
  // This is not the Unity assets folder.
  // You'll want to make sure this image appears in the
  // generated Visual Studio project because it won't get
  // pushed from Unity in any way.
  var images = new string[] { "ms-appx:///assets/WideLiveTile.png" };
  Tiles.updateTile(TileTemplateType.TileWideImage, null, images);
#endif
  }
}

Via Preprocessor Directives You can also use preprocessor directives to enable or disable compilation of inline code. This is a common technique when sharing code among platforms across a variety of technologies and is also used very often in Unity games. With this method, you simply use a directive in your code class. Preprocessor directives can be used for various purposes. The important rules to remember are: Separate your code by platform with a platform-specific preprocessor directive; some preprocessor directives become active the moment you switch platforms in Unity build settings (like UNITY_METRO); some become active only upon compilation outside of the editor (NETFX_CORE); others may be available all the time (such as the check for Unity version, UNITY_4_5, and other custom directives you define).

I’ll show you an example using some Windows platform-specific code. If I want to access GeoLocation in the Windows Runtime, I can include this code directly in my MonoBehavior-derived class (as shown in Figure 4), which can be assigned to any Game­Object. Because this code is compiled in the Editor with Mono, it will fail without wrapping it in a preprocessor directive. We need to tell Unity this code is only compiled when outside of the Editor. You might wonder what the difference is between NETFX_CORE and UNITY_METRO. The former is a compilation setting and is used only when your game assemblies are compiled for the Windows Runtime. The latter is used when you’ve selected Windows Store as the platform in the Unity build settings. This can be active in your C#, UnityScript or Boo code. I personally prefer the NETFX_CORE directive to wrap my WinRT code rather than UNITY_METRO, as NETFX_CORE is only available on export/build and UNITY_METRO is active in the Editor as soon as you switch platforms in the Build Settings. This means code can run while in the Editor, which can be a problem if it contains a platform-specific API. You can add other direc­tives on the same line such as && !UNITY_­EDITOR, but I prefer just NETFX_CORE.

Figure 4 Using Geolocation

public class FindLandTarget : MonoBehaviour
{
// If you’re compiling for the Windows Runtime, use this code
// to GeoLocate on object collision.
#if NETFX_CORE
  void OnCollisionEnter(Collision collision)
  {
    Debug.Log("Collided with " + collision.gameObject.name);
    GetGeoLocation();
  }
  async void GetGeoLocation()
  {
    // Must call geolocation on the UI thread, there's a UI piece to be shown.
    UnityEngine.WSA.Application.InvokeOnUIThread(
      async () =>
        {
        var locator = new Windows.Devices.Geolocation.Geolocator();
        var position = await locator.GetGeopositionAsync();
        Debug.Log(string.Format("{0}, {1}  Accuracy: {2}",
          position.Coordinate.Latitude, position.Coordinate.Longitude,
          position.Coordinate. Accuracy));
        }, false
            );
    /**/
  }
#else // When you’re not using the Windows Runtime, use this collision code instead.
  void OnCollisionEnter(Collision collision)
  {
    // Non-Windows Runtime platforms, no geolocation.
    Debug.Log("Collided with " + collision.gameObject.name);
  }
#endif
}

Builds

Unity will compile your Windows Store and Windows Phone 8.1 code using the .NET Framework, specifically the Windows Runtime. It doesn’t use Silverlight for Windows Phone 8.1. However, the Windows Phone 8 code is compiled as HH, a Silverlight package for Windows Phone, as expected.

Unity will compile your game assemblies and create a Visual Studio solution that you in turn will use to create your final build. In other words, apart from when doing a desktop build, you’ll need to do your final compilation in Visual Studio before sending your game to the Windows Store or Windows Phone Store. The generated Visual Studio solution contains the Unity binaries packaged with your game assemblies and a basic XAML/C# or C++ host app. Every time you build from Unity, the only thing that’s overwritten by Unity is your Data folder. Any custom code or other changes you make to your Visual Studio solution aren’t overwritten during future builds from Unity.

Windows Store and Universal App Builds

I’ll take a look at the build options for Windows Store, which are shown in Figure 5. The Windows Store build types in Unity include Windows 8, Windows 8.1, Windows Phone 8.1, and Universal solutions, which contain both Windows Phone 8.1 and Windows 8.1 projects and a shared project, as shown in Figure 6. Also note the Unity C# Projects checkbox in Figure 5. This is an incredibly useful feature that I strongly recommend. It will create the Visual Studio solution with additional projects containing your Unity code, as shown in Figure 7. You can actually change code in these projects to a certain extent and upon compile Visual Studio will ask Unity to reprocess your game assemblies without having to do a full build again from Unity. This means you can edit your Unity code in your final Visual Studio solution, which is amazing for platform debugging—it means you don’t have to rebuild your solution from Unity every time you make a code change.

Building for Windows Store
Figure 5 Building for Windows Store

A Universal App with a Shared Project
Figure 6 A Universal App with a Shared Project

Additional Projects
Figure 7 Additional Projects

When Unity generates your Visual Studio solution, there are several things to note. First, your Windows Store project will default (as of this writing) to an ARM build platform, not x86. This can be very confusing when you try to build and run because you’ll get an error that your system isn’t an ARM architecture. While I do recommend you create builds for both ARM and x86, for local testing you’ll want to choose x86 to avoid that ARM error. Also, as of this writing, there are no 64-bit players on Unity for Windows Store or Windows Phone. If you have one of the few ARM Windows 8 devices, such as the Surface 1 or Surface 2 (RT not Pro; Pro is an x86-based system), then by all means you can choose ARM and do a remote deployment and debugging to it. However, most developers use an x86-based PC for local testing.

Next, you’ll note that the Build Configuration Type includes Debug, Master and Release options. This is in contrast to typical .NET applications, which include only Debug and Release. The Debug build is the slowest. It contains debugging information and also supports the Unity Profiler—a performance tool in the Pro version used for optimizing games. The Release build is fully optimized but also supports the Unity Profiler. The Master build is the one you submit to each store. This is the optimized, production-ready version and it does not support the Unity Profiler. When I first test a game, I choose a Master build so I can get a true idea of the performance on my device.

For Windows Phone, the two main choices are whether to build for Windows Phone 8 or for Windows Phone 8.1. Windows Phone 8 apps will run just fine on a Windows Phone 8.1 device, although the code-sharing strategy for platform-specific code is much better on Windows Phone 8.1 because you can target universal apps, which share around 90 percent of the API with Windows Store apps. For a typical game, however, this code sharing may not have much meaning unless you’re writing platform-specific code.

Once you have your solution in Visual Studio, packaging it up and sending it to the store is the same as for any Windows Phone or Windows Store application. A Windows Store developer account is a requirement; you pay once and have it for life. That submission process has been covered many times before, but for a quick overview see “Publish to the Windows Store” (bit.ly/Za0Jlx), “Publish to the Windows Phone Store” (bit.ly/1rdDCwR) and “Why and How to Port Your Unity Game to Windows and Windows Phone” (bit.ly/1ElzrcL).

Player Settings I discussed the basic process of building from Unity to Windows, but didn’t look at how you can set icons, splash screens, the app name and other required items. These can all be found in the Player Settings, which is loaded from the Build Settings screen and allows you to configure all the major settings for Windows Store and Windows Phone applications, as shown in Figure 8. You can specify the splash screen, app name, publisher, compilation settings, icons, app capabilities like location services, and a few other settings here. These settings get pushed down to your Visual Studio solution the first time you build your solution from Unity.

Player Settings for Windows Store
Figure 8 Player Settings for Windows Store

App Icons Unity provides some default icons for your application so it will build in Visual Studio. You must change these default icons or risk failing certification. Unity makes it pretty easy to see what images you can set on your project, but refer to the certification documents for each platform to determine which images are required. It’s imperative you check your Visual Assets in the Package.appxmanifest file in Visual Studio (for Windows Store and universal apps) as Unity may have set some default images that you aren’t going to replace with your own and will need to be removed.

At a minimum, Windows Store apps require a 50x50 Store logo, a 150x150 square logo, a 30x30 square logo, and a 620x300 splash screen, as described on the Windows Dev Center (bit.ly/1vIJsue). Windows Phone 8 apps require the app list image and an image for the small and medium default tiles for the Start screen as described on the Windows Dev Center (bit.ly/1oKo8Ro). Windows Phone 8.1 apps require the app list image and default tile images, as well. The stores (which are said to be unifying with Windows 10) may ask for some other images during submission, such as screenshots.

If you’re going to provide just a single image for Start screen tiles, you should provide the image scaled to 240 percent for Windows Phone Store apps and 180 percent for Windows Store apps as per the Windows Dev Center (bit.ly/1nzWber).

By the way, a while back I wrote a no-frills utility to help generate images for Windows Store apps. Check it out at bit.ly/ImageProcessor.

Rebuilds and Overwriting Recall that Unity overwrites just your Data folder in your Visual Studio project (see Figure 9). This is a double-edged sword. You can set the splash screen, icons, and so on at any time in Unity (and I recommend doing so), but if you’ve already generated your Visual Studio solution, the Package.appxmanifest file that contains these settings will not be overwritten the next time you build from Unity. You have to manually set the visual assets, capabilities and so forth in your Visual Studio solution in the Package.appxmanifest file; or build to a new folder and diff the folder structure using a diff tool like BeyondCompare; or delete your Visual Studio solution if you have no custom code in it and let Unity regenerate it. I typically choose the third option because I keep my icon and splash screen images configured inside Unity. I just have to remember to bring in my custom live tile images into my Visual Studio solution. If you’re building for Windows Phone 8 (but not 8.1), the icon must be set in Visual Studio anyway; that’s one of the few things that isn’t pushed from Unity.

The Data Folder in a Visual Studio Project
Figure 9 The Data Folder in a Visual Studio Project

Wrapping Up

The build process is extremely simple. Bring up build settings, click build, open solution, deploy. I showed options for customizing your builds via plug-ins and preprocessor directives. Because you can call platform-specific code outside of Mono, you have some power at your fingertips. Don’t forget to check out prime31.com for Unity plug-ins that are currently free for the Windows platform. They allow you to easily integrate platform features with just a couple lines of code. Keep an eye on Channel 9 for some new bite-sized Unity training content (think 10-minute videos) and on my Channel 9 blog for many mini-tips for building games for the platform. Until next time!

Additional Learning


Adam Tuliper is a senior technical evangelist with Microsoft living in sunny SoCal. He is an indie game dev, co-admin of the Orange County Unity Meetup, and a Pluralsight author. He and his wife are about to welcome their third child, so reach out to him while he still has a spare moment at adamt@microsoft.com or on Twitter at twitter.com/AdamTuliper.

Thanks to the following technical experts from Unity for reviewing this article: Tomas Dirvanauskas, Ignas Ziberkas and Tautvydas Žilys