Special Windows 10 issue 2015

Volume 30 Number 11

Game Development - Write Games for the Universal Windows Platform with Unity

By Jaime Rodriguez | Windows 2015

Windows 10 has many new features to offer game developers and gamers. With the Universal Windows Platform (UWP), developers can target Windows 10 tablets and PCs, Windows 10 mobile devices (that is, phones), Xbox One and HoloLens with a single code base. In addition, the Windows Stores have converged into one Store, and Microsoft has brought Xbox Live Services to Windows 10, along with the Xbox app to boost gamer engagement across all the Windows device families.

For game developers, Unity is one of the most popular game development engines. With support for 21 platforms, it has the best cross-platform development support of any middleware available today. Its editor, combined with support for C# scripting, make it an extremely productive game development environment. With the Asset Store, the Unity community, and the growing capabilities of Unity with ads, engagement, and analytics, it has never been easier to develop an immersive game.

When the stars align, we must write about it! This article will give you all the details you need to get your Unity games running great on Windows 10. This isn’t an introduction to Unity or an introduction to UWP apps. We assume you’re already familiar with both of these topics and, instead, we’ll focus on explaining what has changed with Windows 10 and the “must-know” tips required to create great Universal Windows Games (UWGs!). We’ll do this in a hands-on approach, walking you through a few changes we made to a sample game called Chomp (see Figure 1) to optimize it for Windows 10.

Chomp
Figure 1 Chomp

Chomp started life as a Windows 8.1 game written with Unity. As you can see from the screenshot in Figure 1, it’s a pretty simple maze game similar to Pac-Man. This sample was created as a guide for developers to demonstrate how to write a game with Unity, so simplicity was key. But, with Windows 10 becoming available and Unity supporting the new OS, Chomp had to be updated. You can find the source code for Chomp at bit.ly/UnityChomp. Download it and follow along in our journey.

To get a UWP version of our game, we could simply export the game using the Windows 10 profile in Unity, but this doesn’t produce an application optimized for the way Windows 10 works. It doesn’t handle running in a window, full-screen mode, touch and so on. So, let’s look at what we did to take this game from Windows 8.1 to Windows 10.

Getting Started (Prerequisites)

UWP apps (and UWGs) require that you develop and test with Windows 10 and with Visual Studio 2015. Any Visual Studio 2015 edition will have everything you need to create your games, including Visual Studio Community 2015, which is free!

On the Unity side, you need Unity 5.2.1p2 or higher. Unity 5.2 now installs Visual Studio Community 2015 and Visual Studio 2015 Tools for Unity (VSTU), so, in practice, to get started all you need to install is Unity and check the right options during the install process. See Figure 2 for details.

Installing Unity with the Correct Options Gives You Everything You Need to Get Started
Figure 2 Installing Unity with the Correct Options Gives You Everything You Need to Get Started

Note: For developers using a Mac, a new alternative is to use the Visual Studio Code editor with Unity projects. You can find more details about that option at bit.ly/UnityVSCode.

Building for Windows 10

Building for Windows 10 follows the exact same process with which you’re already familiar. There’s a new SDK to target UWP apps under the Windows Store platform (see Figure 3), which will export the game as a UWP app.

Targeting Windows 10 from Unity
Figure 3 Targeting Windows 10 from Unity

Here are some of the important items happening under the hood during the export for Windows 10 and UWP development:

  • There are new UNITY_UWP and UNITY_WSA_10_0 pre-processors that you can use to “tailor” your game logic and experience for the UWP.
  • Unity 5.2 now includes a new streamlined WinRTLegacy DLL that contains fewer types than prior versions. With Windows 10, Microsoft has brought several types back into the .NET Core profile, making some of the workarounds that WinRTLegacy included no longer necessary.
  • Unity 5.2 is using the new plug-in model introduced in Unity 5. This greatly simplifies plug-ins that participate in your workflow, as you’ll see later in this article.
  • Unity 5.2 includes experimental support for DirectX 12, which ships with Windows 10. To try the experimental support, open Player Settings in Unity, uncheck the Auto Graphics API option and manually include Direct3D12 support.

New Project Templates 

The Unity build process now generates a Visual Studio 2015 project compatible with the UWP. As you probably already know, there are some significant changes to this new project system.

For example, each UWP app now ships with its own copy of .NET Core within the app, so you always get the .NET version with which you tested. To accommodate this, Unity generates an appropriate project.json file that will pull in the proper .NET “pieces” via NuGet.

Also, UWP apps use .NET Native, which generates optimized, native machine code before your app is downloaded to customer machines and leads to faster launch times and lower battery consumption for your games. The impact of these optimizations will vary based on the complexity of your game, but they definitely won’t hurt performance. The only caveat with .NET Native is that it does lead to (significantly) longer compile times within Visual Studio. For regular apps, Visual Studio only compiles with .NET Native for the “Release” configuration of the project. With Unity’s generated project file, a similar approach is implemented and only the “Master” configuration is compiled using .NET Native. If you aren’t familiar with the configuration targets in Unity, there are three:

  • Debug is a full debug project with no optimizations.
  • Release is a project compiled with optimizations, but it includes profiler support.
  • Master is the configuration you should submit to the Store, as it has no debug code, all optimizations are enabled and profiling support is stripped out.

You definitely should be compiling and testing with .NET Native early in your development cycle. Unity does a lot of advanced inter­mediate language (IL) weaving, so if there’s any type of app that stresses .NET Native to its fullest, it’s a Unity game. To ensure things are working as expected, watch out for warnings in the output window during .NET Native compilation.

The aforementioned differences are significant at run time, but the new Unity templates make these changes transparent to you as the developer, so let’s focus on how to tailor and polish your game for Windows 10.

Tailoring and Polishing Your Game for Windows 10

One code base across many form factors is a key feature of the UWP, but, when it comes to games, there might still be some tailoring and optimizations necessary for specific form-factors. Most often, these include: input mechanisms (such as touch, keyboard, mouse and gamepad); window resizing; optimizing resources and assets; and implementing native platform integration—such as live tiles, notifications or Cortana—with each specific form-factor. We’ll explore what these look like for UWGs.

Windowing Universal Windows apps are now hosted in resizable windows instead of running full screen as they did in Windows 8 and 8.1, so windowing is now a consideration for your games and applications. Most of these differences are transparent to you as a Unity developer because the Screen.height and Screen.width properties still report the available space in native (pixel) sizes.

Windows 10 also includes new APIs to enter and exit full screen, and these are exposed via the Unity Screen class by setting the Screen.fullScreen property. A best practice around windowing is to implement the standard key accelerators to enter and exit full screen. These vary widely across publishers, but a common accelerator to toggle in and out of full screen is F11 or Alt+Enter. For Chomp, we wanted to give players this option to play in full screen, so we toggle full-screen mode by doing the following:

if (Input.GetKeyUp (KeyCode.F11))
{
  Screen.fullScreen = !Screen.fullScreen;
}
if (Input.GetKeyUp (KeyCode.F11))
{
  Screen.fullScreen = !Screen.fullScreen;
}

Having a multi-window desktop introduces another required change for Windows 10 games: You must handle focus changes. In a multi-window desktop, if your game window doesn’t have focus, you should pause your game and your music, as the user might be interacting with a different window. Unity abstracts this interaction with the same API it exposes in other platforms: the OnApplicationPause method. This method is called on all active MonoBehaviours when focus has changed. We handle this in Chomp as shown in Figure 4.

Figure 4 Pausing Your Game When Focus Changes

public void OnApplicationPause(bool pause)
{
  FocusChanged(!pause);
}
public void FocusChanged(bool isFocused)
{
  if (isFocused)
    musicSource.UnPause();
  else
  {
    musicSource.Pause();
    GameState.Instance.SetState(GameState.GameStatus.Paused);
  }
}

Notice there’s asymmetry: When a game loses focus, the game and audio are paused, but when it receives focus we un-pause the audio only. This happens because when the game pauses, we also show a paused dialog box in the game itself, and when focus is resumed, the game waits for the user to confirm he wants to resume gameplay. The dialog handles setting the game state back to Running from Pause.

With these two changes in place, we properly handle the ability to enter/exit full screen and pause the game when our window loses focus.

Input Earlier releases of Unity had great support for input in Windows games, and this hasn’t changed with Windows 10. Mouse, touch and gamepad remain neatly abstracted by the Input class and the Input Manager in Unity.

The most important thing to remember regarding input is to ensure you’re implementing as many input mechanisms as make sense for your games. For Chomp, we want to support keyboard, gamepad and touch. Remember that UWGs can run everywhere, so give your players the best input/gaming experience you can. The most frequent question we see around input is how to detect if you need to show touch controls (like a virtual joystick or D-pad) when you’re running in a touch device such as a phone.

One way to determine if the touch joystick should be shown is to determine if the game is running on a phone. If so, it would make sense that the joystick would be displayed and enabled by default. To determine if the game is running on a specific platform (such as a phone or Xbox), you can check if the appropriate contract is implemented. This is how Chomp detects if it’s running on Windows 10 Mobile:

public static bool IsWindowsMobile
{
  get
  {
    #if UNITY_WSA_10_0 && NETFX_CORE
      return Windows.Foundation.Metadata.ApiInformation.
        IsApiContractPresent ("Windows.Phone.PhoneContract", 1);
    #else
      return false;
    #endif
  }
}

Note that in this code we use the UNITY_WSA_10_0 pre-processor to determine if we’re compiling for Windows 10. Without this check, the code would fail to compile on non-Windows 10 builds.

Having the virtual joystick visible at all times is one approach, but it might be a better option to only show the joystick when the user is actually using touch on a device. Windows 10 includes a new API that will determine whether a user is running Windows 10 in Tablet mode (touch) or traditional desktop mode (mouse/keyboard):  Windows.UI.ViewManagement.UIViewSettings.User­InteractionMode. This API must run on the Windows UI thread, so from within Unity you must marshal the call to the UI thread. We added the code shown in Figure 5 to Chomp to determine if the user is interacting with the app using touch.

Figure 5 Code to Determine if User Is Using Touch

public static bool IsWindows10UserInteractionModeTouch
{
  get
  {
    bool isInTouchMode = false;
#if UNITY_WSA_10_0 && NETFX_CORE
    UnityEngine.WSA.Application.InvokeOnUIThread(() =>
    {
      isInTouchMode =
        UIViewSettings.GetForCurrentView().UserInteractionMode ==
        UserInteractionMode.Touch;
    }, true);        
#endif
    return isInTouchMode;
  }
}

Now with these two methods implemented, we can update Chomp to make an educated guess on when to show the joystick. If the game is running on a mobile device, or the user interactive mode is touch, UseJoystick will return true, and we display the joystick:

public static bool UseJoystick
{
  get
  {
    return (IsWindowsMobile || IsWindows10UserInteractionModeTouch) ; 
  }
}

With windowing and input handled, we can now move on to take advantage of new native Windows APIs to add more functionality to our game.

Native Integration with Windows 10: Platform Light-Up Native integration with the OS from within a Unity game is handled the same way it was previously: If you’re compiling using the .NET Core compilation option in Unity (using the NETFX_CORE pre-processor), you can inline native code, as our previous examples showed.

If the code you want to add is more than you want to inline, or the behavior needs to be abstracted (across platforms), you can still use plug-ins. For Windows 10, the Microsoft Developer Experience Games Evangelism team (that we’re a part of) is open sourcing several new plug-ins to make it easier for you to integrate with Windows 10. You can find these plug-ins at bit.ly/Win10UnityPlugins. As of today, the following plug-ins have been shared:

  • Store: A Store plug-in for in-app purchases with support for app simulator, consumables, durables and receipts. Everything you need to transact with the Windows Store is here.
  • AzureMobile: A Microsoft Azure plug-in with basic Create, Read, Update, Delete (CRUD) operations for Azure Storage.
  • Core: A “core” plug-in that offers native integration to core OS features such as live tiles, local notifications, push notifications and Cortana.
  • Ads: A plug-in that wraps the new Windows 10 Microsoft Ads SDK, now with support for video interstitials.

Previously, Chomp didn’t have in-app purchases, so we decided to add them to the game using the Store plug-in. Now, Chomp has support for purchasing consumables (boosters) and durables (mazes).

The easiest way to use these plug-ins is to download the Unity package from GitHub and import it into Chomp using the Assets | Import Package | Custom Packages in Unity Editor. Once the package is imported, you’ll have the proper binaries located in the Unity Plugins folder. Once installed, the binaries can be found in the Plugins\WSA directory; Unity requires placeholder assemblies (compatible with the Microsoft .NET Framework 3.5) to be used within the editor, so those are also included and copied to the Plugins folder itself.

After importing the package, we can now reference the Store APIs from within Chomp. We first call Store.LoadListingInformation, providing a callback method that runs upon completion, to get a listing of all the items available for purchase. If the call succeeds, we iterate over the ProductListing items returned and use those to populate the prices in our UI, as shown in Figure 6.

Figure 6 Listing Items Available for In-App Purchase

void Start()
{   
  Store.LoadListingInformation(OnListingInformationCompleted);
  ...
}
void OnListingInformationCompleted(
  CallbackResponse<ListingInformation> response)
{
  if (response.Status == CallbackStatus.Success)
  {
    ListingInformation result = response.Result;
    PopulatePrices(result.ProductListings);
  }
}

Once the user has selected the item he wants to purchase, executing the transaction is just a few more lines of code. Figure 7 shows the code we added to purchase a durable (new mazes for the game).

Figure 7 Making an In-App Purchase

public void OnDurablePurchase(GameObject buttonClicked)
{
  string productId = GetProductId(buttonClicked.name);
  if (!string.IsNullOrEmpty (productId))
  {
    Store.RequestProductPurchase(productId, (response) =>
    {               
      if (response.Status == CallbackStatus.Success)
      {
        // response.Status just tells us if callback was successful.
        // The CallbackResponse tells us the actual Status
        // as returned from store.
        // Check both.
        if (response.Result.Status == ProductPurchaseStatus.Succeeded)
        {
          EnableLevels(productId);
          return;
        }                 
      }
    });
  }
}

As you can see, it’s straightforward to use these new plug-ins to implement native functionality.

Submitting to the Store

Submitting to the Windows Store is easier than ever. You can now submit one single package that includes all binaries, or you can submit a package for each platform/architecture, if desired.

If you want to split your packages or support your game only on specific platforms, you can manually edit the package.appxmanifest file and tweak the TargetDeviceFamily element:

<Dependencies>
  <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" 
    MaxVersionTested="10.0.10240.0" />
</Dependencies>

The three possible device families are:

  • Windows.Universal: This allows your binaries to be deployed everywhere that meets your hardware requirements.
  • Windows.Mobile: This should be used for binaries that go into the Windows 10 Mobile SKUs, namely Windows Phone, though in the future there will likely be other small devices (six inches or smaller) that aren’t phones and run this SKU, so don’t assume it’s just phones.
  • Windows.Desktop: This should be used for games that can only be played on desktop and tablets.

If you want to target mobile and desktop, but not console or other later families of Windows, you can have two device families in your manifest, like so (replace “x” and “y” as appropriate):

<Dependencies>
  <TargetDeviceFamily Name="Windows.Mobile" MinVersion="10.0.x.0"
    MaxVersionTested="10.0.y.0"/>
  <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.x.0"
    MaxVersionTested="10.0.y.0"/>
</Dependencies>

Notice that you can have different MinVersion and MaxVersions for each device family. This will be handy in the future as Windows 10 Mobile will ship with a later version number than Windows 10 desktop. However, for now, we recommend you leave the default versions (10.0.10240.0).

As mentioned earlier when we discussed .NET Native, when submitting your packages, make sure you submit the Master configuration. Also, we recommend you include the full program database (PDB) symbol files for crash analytics. The new Store doesn’t have the option to download cabs to analyze them locally. Instead, you must submit your PDBs to the Windows Store, and the Store does the work for you, giving you stack traces for the crashes (see Figure 8).

Including Program Database Symbol Files
Figure 8 Including Program Database Symbol Files

Finally, when you submit to the Windows Store via the developer portal, make sure you choose the right hardware configuration. The Store now lets you specify hardware requirements such as touch or keyboard, so your game is only installed on the right devices (see Figure 9).

Hardware Preferences Available in Developer Portal
Figure 9 Hardware Preferences Available in Developer Portal

There’s Lots More!

This article gives you a brief “what’s new under the hood” for Unity developers by showing how we ported our simple game to Windows 10 and added a few new features. With our limited space, we focused on the foundations and game-specific “must-dos” instead of showing you every new feature in the Windows 10 platform. If you want to have a great, immersive game, consider taking advantage of additional features such as the new notification center (to drive engagement) on desktop, Cortana, the new live tile templates and the new Xbox Live Services APIs. With Windows 10, Microsoft is gradually opening up access to Xbox Live Services. You don’t need to write a console game—you just need to have a great game running on Windows 10 and want to take advantage of the services such as leaderboards, achievements, cross-device play and so on. To apply for access, sign up for the ID@Xbox program at xbox.com/id.

Visual Studio 2015 Tools for Unity

Starting with the 5.2 release, Unity includes Visual Studio 2015 Tools for Unity (VSTU), making Visual Studio the new default code editor for Unity projects on Windows. This change will bring improved IntelliSense, syntax coloring in the editor and a great C# debugger. To configure your default script editor, select the Edit | Preferences menu option in the Unity Editor. Your choices might include MonoDevelop (built-in), Visual Studio 2015, Visual Studio 2013 or the option to browse for further options.

VSTU also includes a few shortcuts for more easily writing code for Unity. For example, if you right-click within a MonoBehaviour class, the context menu will have a new Implement MonoBehaviours entry, which lets you quickly inject a MonoBehaviour method signature into your class.

In that same context menu, there’s also a Quick MonoBehaviours entry, which performs a similar function but with a less-intrusive dialog where you can type the method name you’re searching for, and the signature is again injected. Both of these methods are accessible from shortcut key accelerators for even more rapid use (Ctrl+Shift+M and Ctrl+Shift+Q).

Beyond the editor enhancements, one of the best features when using VSTU is the streamlined debugger integration with the Unity Editor. When a Unity project is open in Visual Studio, you’ll automatically see an “Attach to Unity” button for debugging in the standard Debug toolbar. Figure A shows where this button is located. This button will automatically find the Unity Editor’s process and attach to it. From there you can seamlessly set breakpoints, analyze variable values and do most everything else you’d expect to do with Visual Studio. VSTU even has experimental support for breaking on exceptions. For even more details on VSTU 2.0 features, check out the blog post, “Visual Studio Tools for Unity 2.0,” at bit.ly/VSTUInfo.

Note: If you aren’t targeting Windows 10 and using Visual Studio 2013, there’s a downloadable package that brings all the goodness we described here to Visual Studio 2013 Community Edition users. You can download this extension at bit.ly/VSTU2013.


Jaime Rodriguez leads the Microsoft Developer Experience Games Evangelism team. You can find him on Twitter: @jaimerodriguez and via his blog at jaimerodriguez.com.

Brian Peek is a senior game developer evangelist at Microsoft. He’s a hardcore gamer and has been developing games on Windows, consoles and anything else that can be programmed for as long as he can remember. You can spot him around the country speaking at developer conferences, or follow him on Twitter: @BrianPeek and via his blog at brianpeek.com.

Thanks to the following Microsoft technical experts for reviewing this article: Sanjeev Dwivedi and Adam Tuliper
Sanjeev Dwivedi is a senior game developer evangelist at Microsoft. Reach him at sanjeev.dwivedi.net.

Adam Tuliper is a senior technical evangelist at Microsoft. Reach him on Twitter at @AdamTuliper.