Udostępnij za pośrednictwem


Azure and Unity3d - AssetBundle Delivery

This article provides an illustration of how Microsoft Azure could be used as a simple means of delivering content to a Unity game. In this scenario, a game will query Azure to retrieve and load the most recent version of a particular scene. There are many ways of solving this requirement including using platform specific patching (e.g, Google Play, iOS store) and it is a common expectation with modern games.

Unity3d

Unity is a game development platform that can be used to develop both 3D and 2D games and supports building for a large variety of platforms including Android, Windows, Xbox, iOS and other platforms. Unity supports javascript and C# as development languages but an important fact to emphasize is the engine uses the C# compiler Mono to build the game.

Because Unity uses the Mono compiler, this means the version of our assemblies are limited to .Net 3.5 or lower as shown when the Microsoft ServiceBus library, for example, is directly referenced:

Note, it is possible to include more recent .Net assemblies using the experimental setting.  Though the editor is continually being improved the Experimental setting is experimental and therefore might not be viewed stable enough to include for public builds.  The option can be found in PlayerSettings under Configuration in the Unity editor:

Mono

Mono is an open source development platform used to build cross-platform applications. Supported by Microsoft and the .NET Foundation, the Mono project has an active and enthusiastic contributing community.

Non-.Net Platforms

Another important factor about creating games with Unity is the platform the game will be built to run on.  If for example, the target platform includes Android or iOS then directly referencing .Net assemblies will not be supported.

AssetBundles

Unity supports the feature of packaging assets into an AssetBundle.  These bundles can contain Models, Tetures, Prefabs, Audio Clips and scenes.  These bundles can be loaded at runtime so are ideal for downloadable content (DLC) and/or only loading the required assets for a specific installation.  Please see Unity's documentation on AssetBundles for more information including the initial step of including the Build AssetBundles menu option.

For the following scenario, a simple script was created to illustrate how menu options for the Android and Windows platform can be supported:

The menu options were created as follows (be sure to create in a folder called Editor):

[code lang="csharp"]

using System.IO;
using UnityEditor;

public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles/Windows64")]
static void BuildAllWindows64AssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles/WindowsAssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}

[MenuItem("Assets/Build AssetBundles/Android")]
static void BuildAllAndroidAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles/AndroidAssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.Android);
}
}

Azure Integration in Unity

Because of the limited .Net version support and the restriction in directly referencing .Net assemblies, it is a common approach for Unity solutions to use the supported web APIs for a given Azure resource.  This post will provide an example of retrieving files from Azure Blob Storage using Azure Storage Services REST API.

The wiki post Connecting Unity3d to Azure Service Bus provides an example of connecting to an Azure Service Bus.

Illustration of retrieving Unity packages from Azure Storage

The following illustrates loading a scene from Azure.  The Unity project will consist of two scenes: BootstrapperScene and EchoScene.  The Bootstrapper scene will retrieve and load the EchoScene.

Azure Storage

In Azure we will use Blob Storage to hold the latest version of our scene. For background on Azure Storage please see the Microsoft documentation.  For this illustration the storage account will be created and given public access to read blobs.  This can be done in the portal by selecting a created container and setting the access policy:

In this example, the AssetBundles created for the Windows platform will be deployed in the WindowsAssetBundles folder.  This is to illustrate a potential bundling strategy where platform specific bundles are created and loaded at runtime.

Unity creating an AssetBundle

To create the AssetBundle, the first step is to select the entity to be bundled.  In this case, the EchoScene is selected in the project.  Notice the Asset Labels section in the Inspector:

In the Asset Labels section, a new bundle will be created called echoscenebundle:

The final step is to generate the bundle using the Build AssetBundles menu option.  Once the file is created then the bundle should be uploaded to Azure using the Upload option:

Loading an AssetBundle at runtime

A script will be added to the scene to control the loading of the echoscenebundle named Bootstrapper.  The first step is to start a co-routine to load the bundle from Azure.  This routine will retrieve the given name from storage:

[code lang="csharp"]
public IEnumerator LoadAssetAzureRoutine(string name)
{
bool hasLoaded = false;
int retry = 0;

var url = string.Format("https://{namespace}.blob.core.windows.net/assetbundles/{0}", name);

do
{
WWW request = WWW.LoadFromCacheOrDownload(url, 1);
yield return request;
AssetBundle bundle = request.assetBundle;

if (bundle == null)
{
Debug.LogErrorFormat("Failed to load AssetBundle {0}!", name);
retry += 1;
}
else
{
_bundle = bundle;
hasLoaded = true;
}
}
while (hasLoaded != true && retry < 3);
}

The next step is to load the scene once the bundle has been loaded.  An important thing to note is the scene name is the scene path loaded from the bundle:

[code lang="csharp"]
IEnumerator LoadFirstScene()
{
yield return null;
yield return SceneManager.LoadSceneAsync("Assets/IGL/EchoScene.unity");
}

Summary

For games requiring hosted services, Azure makes a lot of sense with its breadth of functionality and the affordable cost.  Even indie game developers can take advantage of the Free Azure subscription.  Of course larger companies have already built sophisticated solutions using the platform like NextGame's Walking Dead No Man's Land and Respawn Entertainment's Titanfall.

For additional information see Azure for gaming

The source can be downloaded from the git repo.

Comments

  • Anonymous
    December 15, 2017
    Very interesting post, Jeff. This can be a good approach for developing HoloLens apps as well.
  • Anonymous
    December 15, 2017
    This is one of those things that hadn't really crossed my mind as a use case for Azure. But I like the idea!