Upgrading to Unity3d 5 Asset Bundles

This article is part of a series. If you’d like to skip ahead, you can go to the master post that links to them all.
In my first installment of this asset bundle series, let’s talk about upgrading an older project to Unity 5 bundles.

On this latest project I’ve been working on with ClutchPlay Games, I was asked to help straighten out a project that was based on the pre-Unity 5 bundle system. We did a lot to help it. First we added the Android GPU class support first, making sure everything worked. But our build times were taking forever, even with code that checksummed the source assets and only building what changed. So I decided to solve it with a crazy idea: let’s move this project up to Unity 5’s new bundle system.

In Unity 5’s asset bundles, they take care of tracking all the source asset changes for you. It has many upsides: it’s really fast to make small changes. It’s super easy to add assets to any given bundle with the new UI. Building them is a single call, and it works reliably. The sample code for loading the bundles is clean and useful, took less than a day to integrate, and only a week to make it solid. If you’re starting a new project, I highly recommend adding support for this early, it will definitely make certain distribution problems very easy.

But what is the value added for projects that still use the older system? On the surface they look completely incompatible. Assets were always added from code, which is perfect for build automation, very wise in large projects. You don’t want to manually set every asset’s bundle identifier through the UI. That alone would simply take too long. Then you notice the new BuildAssetBundles call that takes the AssetBundleBuild objects. Surely this is how.

But lo! ‘Tis not true. It’s simply not well documented. You can have the best of both worlds. Simply replace your old calls to BuildPipeline.BuildAssetBundle() with a method that changes the asset bundle assignments for each asset that you would pass to BuildAssetBundle. How, you say? Simple: it’s now part of the AssetImporter interface.

AssetDatabase.StartAssetEditing();

for ( string assetPath in desiredAssets ) {
	var importer = AssetImporter.GetAtPath(assetPath);
	// note that you must set the bundle name before the variant.
	// If you want to clear the bundle name, set it to null - it will clear variant for you.
	if (importer.assetBundleName != bundleName)
		importer.assetBundleName = bundleName;
	if (importer.assetBundleVariant != variant && bundleName != null)
		importer.assetBundleVariant = variant;
}

// this might be a little extreme but we've had issues with old versions being used in builds
AssetDatabase.StopAssetEditing();
AssetDatabase.SaveAssets();
EditorApplication.SaveAssets();
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);

At that point, everything will be assigned to the bundle names you want. As a separate step you then actually build the bundles through the simplified BuildPipline.BuildAssetBundles(). As a bonus, you can then examine and tweak the bundle assignments through the Editor UI!
Not all is wine and roses, however. There are a few not-so-obvious rules with the names you use for the bundles.

  • Periods confuse the loading system for some reason. The asset extension is ignored during loading, but extra periods in the asset filename or the bundle names confuse things.
  • Underscores have special meaning in bundle names. It’s safest to avoid using them. Likewise, be sure not to use them in variant names.
  • Bundle names will always be stored lowercase. This prevents case confusion, and is not a bug.
  • Forward slashes create a “group” in the bundle name selection popup. This is highly useful. Be careful not to accidentally put them right together, like “textures//thing2”. It breaks the menu.

There we are! With the new bundle system in place, our build times are down to a few minutes instead of an hour. With this new design, you can do a pass with the bundle assignments, and then edit a specific asset many times, doing only the bundle update over and over again. Because Unity tracks it for you, each bundle update takes only seconds.

There is one more major piece to upgrading an old project. Join us next week as we work out how to handle shared assets!