The Simplest Unity Bundling Example I Could Make

Asset bundles in Unity can be tricky. I’ve spent a lot of time at work developing a pretty slick bundling system. The system pulls the latest from our git repo, then uses manifests to pull in new procedural assets, then generates all the bundles for each level, then uploads them into versioned folders on Amazon S3.

Most big projects will need something like this.

But it’s probably best to start with something simpler. The system I’ve built for work is probably 500 – 1000 lines of code with everything included. This weekend I wanted to find the least amount of code with which I could make a working bundles system.

This system has no extra features. It doesn’t support simulation mode. It doesn’t support procedural assets. It doesn’t support multiple simultaneous downloads. It doesn’t support viewing download progress. But it does work.

Here’s how to get Unity asset bundles working in under 200 lines of code.

Download the AssetBundleManager from the Asset Store

You don’t need the examples. You’re really only using this for the UI features added to the Editor, but some of the included classes in that package are also a good starting point.

Assign assets to bundles

When you select an asset, you should see a drop down all the way at the very bottom of the inspector. Use that dropdown to create a new asset bundle, then add your assets to it.

Create editor script for clearing bundle cache

When you are testing bundles, you will need an extra menu item to delete your local cache. Make an Editor folder somewhere and drop this script in it.

using UnityEngine;
using UnityEditor;

public class BundleOptions
    /// Delete all cached bundles. This is necessary for testing.
    [MenuItem("Assets/AssetBundles/Clear Bundle Cache")]
    static void LogSelectedTransformName()
        if( Caching.CleanCache() )
            Debug.Log("All asset bundles deleted from cache!");
            Debug.LogWarning("Unable to delete cached bundles! Are any bundles in use?");

You will want to click Assets > AssetBundles > Clear Bundle Cache between each generation of bundles to make sure that you are using the latest version in editor.

Create a BundleManager class

Your BundleManager class will download bundles and allow the program to access asset bundles. If you expand this example, then this will be the center of your work.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class BundleManager : MonoBehaviour
    // the web server where your bundles are stored - you can test this locally using file://c:/path-to-bundles/etc
    private static string baseBundleUrl = "file://c:/example/Unity/MyGame/AssetBundles";
    private static string baseBundleUrl = "";

    // this dictionary will store references to each downloaded asset bundle
    private static Dictionary bundles;

    /// Get a reference to an AssetBundle instance that has already been downloaded.
    /// This should be used when you want to load an asset from a bundle.
    /// the name of the bundle to get
    /// a reference to an AssetBundle or null if that bundle has not yet been downloaded or cached
    public static AssetBundle GetBundle(string name)
        if( bundles != null && bundles.ContainsKey(name) )
            return bundles[name];
        return null;

    /// Very simple method for downloading a single bundle.
    /// Extensions to this method may include a progress monitor and a callback for when the download is complete.
    /// the name of the bundle you want to download
    /// an IEnumerator to be run as a Coroutine
    public static IEnumerator DownloadBundle(string bundleName, System.Action downloadCallback = null)
        Debug.Log("Attempting to load bundle " + bundleName + "...");

        WWW www = WWW.LoadFromCacheOrDownload(getFullBundleUrl(bundleName), 1);

        yield return www;

        // if there was a download error, then log it
        if( !string.IsNullOrEmpty(www.error) )
            Debug.LogError("Error while downloading bundle " + bundleName + ": " + www.error);
        else // if there was no download error
            // try to get the downloaded bundle
            AssetBundle newBundle = www.assetBundle;

            // if the bundle is null, then log an error
            if( newBundle == null )
                Debug.LogError("Unable to save bundle " + bundleName + ": Bundle is null!");
            else // if a valid bundle was downloaded
                if (bundles == null)
                    bundles = new Dictionary();

                // store a reference to that bundle in the dictionary
                bundles[bundleName] = newBundle;

                Debug.Log("Successfully loaded " + bundleName + ".");

        // if there is a downloadCallback, then call it
        if( downloadCallback != null )

    /// Return a string representation of the platform that will go into the bundle path.
    private static string getBundlePlatform()
        if (Application.platform == RuntimePlatform.Android)
            return "Android";
        else if( Application.platform == RuntimePlatform.WindowsEditor )
            return "Windows";

        // maybe this is some strange version of Android? Need this for Kindle.
        return "Android";

        // do not support other platforms
        //throw new System.Exception("This platform is not supported!");

    private static string getFullBundleUrl(string bundleName)
        return baseBundleUrl + "/" + getBundlePlatform() + "/" + bundleName;

    // Use this to initialize the bundles dictionary
    void Start ()
        if (bundles == null)
            bundles = new Dictionary();


Modify that script by replacing baseBundleUrl with the place where your bundles are stored locally for development and remotely for production.

You will also need to hook this script into the program somehow. You can attach it to a GameObject if you like, but that isn’t strictly necessary. All you really need to do is start a coroutine to run the DownloadBundle method, then call GetBundle to get the download. Then just call the LoadAsset method on the asset you want to instantiate.

Generate bundles

When you click Assets > AssetBundles > Build AssetBundles, it will generate bundles for whatever platform is selected. You will need to generate bundles for your development machine and for your target platform. Make sure to modify the getBundlePlatform method to support your platform.

And…. ?

And that’s it. Asset bundles are not really that complex when you boil them down. For my music apps, I just want them to store a few extra sound files that I don’t want to distribute with the executable. So a system like this works fine. I just start the download when the app starts.

Of course, for larger projects you will need many more features. Versioning bundles is very important for the development and build processes. Also you will want to show a progress bar on the screen. And you will want to load entire levels into bundles, which is a little more tricky. But hopefully this will get you started on the right track.

Why I Created

When I was teaching at UCSC and SJSU, I taught very large courses, often consisting of over 200 students. Courses that size create lots of infrastructural problems. Communication is a huge problem, but that’s mostly taken care of by Canvas or Blackboard. The bigger problem for me was assessments.

I think that even well-written multiple choice quizzes are not great assessments. In multiple choice quizzes, students always have the answer presented to them. Even very difficult multiple choice quizzes never ask students to explain their reasoning. They never force students to come up with a concept from memory. They present students with the false premise that knowledge is fixed, and is simply a matter of choosing from what already exists.

So I always wanted to use other types of questions, and I did. Or at least I tried to. To incorporate even one short answer question meant hours of grading. I once did a single essay assignment for a large class, and probably spent over forty hours grading essays.

I needed a grading tool that could quickly save me time, while allowing me to diversify the types of assessments I could use on a week-to-week basis. For the past three months I’ve been building a website that automatically grades short answer, essay, and multiple choice questions. I call it, and it’s accepting applicants for the closed beta right now.

The hook of the website is automatic grading, but the purpose of it is to save teachers as much time as possible. So the grader gives a score for every question, but the site then points the teacher to all the “low confidence” scores. These are the scores where the grader didn’t have enough information to be fully confident it gave an accurate score. The teacher can then grade the low confidence responses on a single page, and then they are done!

So the grader is part of a larger process that means that teachers only grade the work that actually needs their attention.

I think this can be a great tool, and I think it will save teachers a lot of time. If you’re teaching a large class this semester, then give yourself a new tool, and try QuizMana.

How Can Comments be Controversial?

Comments add information to your code. They don’t impact the execution of that code. So how can they be bad? I believe that more commenting is better, and that comments are a vital tool in maintaining an agile codebase, but I’ve met many experienced developers who argue with me about comments.

The Pragmatic Programmer is an excellent book. It outlines best practices that have solidified over the last thirty years or so as software development has grown as a field. The authors share these practices as a series of tips that are justified by real world anecdotes. In a section on comments the authors say

“The DRY principle tells us to keep the low-level knowledge in the code, where it belongs, and reserve the comments for other, high-level explanations. Otherwise, we’re duplicating knowledge, and every change means changing both the code and the comments. The comments will inevitably become out of date, and untrustworthy comments are worse than no comments at all”

They make the point that obsolete comments are worse than no comments at all. This is undoubtably true, but it has been bastardized by many programmers as an excuse for not commenting. I’ve heard this excuse, along with two others to justify a lack of comments in code.

  1. The code is self-commenting.
  2. Out of date comments are worse than no comments.
  3. You shouldn’t rely on comments.

In this post I want to address each of these points. I think that thorough commenting speeds up the rate of consumption of code, and that obsolete comments are a failure in maintenance, rather than in comments in general.

1. The code is self-commenting

This is the excuse I hear most often from developers who don’t comment their code. The thinking is that clear variable and method names replace the need for comments. There are situations where this is true. For very short methods with a single purpose, I see that no additional comments may be necessary.

But most methods are not very short, and most methods achieve several things that relate to one overall purpose. So in the first place, very few methods fit the bill.

This is not a valid complaint because good comments only make the code easier to read. While the code may be legible on its own, a comment that explains the purpose of a method, or the reason for
a string operation, can only make it easier to read. The author of Clean Code agrees due to the amount of time we spend reading code.

“the ratio of time spent reading vs. writing is well over 10:1. We are constantly reading old code as part of the effort to write new code. Because this ratio is so high, we want the reading of code to be easy, even if it makes the writing harder.”

Because we spend more time reading code than writing it, a responsible programmer knows that the extra comment in a method which takes very little time to write may well save another programmer many hours of learning.

2. Out of date comments are worse than no comments

To refute this argument, lets take cars as an analogy. If you buy a car, then drive it for twenty thousand miles without an oil change, it will break down. If you did that, the fault wouldn’t be in cars in general. Rather, the fault is in the lack of maintenance.

Similary, obsolete comments are not a failure of comments in general, but a failure of the programmer who updated the code without updating the comments. That other programmers have bad practices does not justify continuing that bad practice.

Obsolete comments are a broken window. If you see them, it is your job to fix them.

So while obsolete comments ARE worse than no comments, that argument is an argument against bad coding practices, not comments in general.

3. You shouldn’t rely on comments

The argument that a programmer shouldn’t rely on comments is a subtle dig at another programmer’s skill. They’re saying “a good programmer can understand this code with no comments.”

There is a grain of a valid point there. If you consider yourself a senior programmer, then you should be accustomed to wading through large volumes of bad code and parsing out the real meaning and functionality.

But even for senior programmers, comments make it easier to read and understand the code. It’s much easier to interpret a one line summary of a block of code than to parse that block line by line. It’s much easier to store that one line in your head than it is to store the whole block in your head.

The real reason why this is the worst of excuses is that not all programmers working on your code are senior programmers. Some are green graduates straight out of college. Yes, a more experienced programmer could understand the code without comments, but it will cost that graduate hours to figure out what they could have gotten in minutes with good comments.

My Commenting Principle

Comment your code so that a green programmer can understand it.


Comment your code so that your boss can understand it.

What does it take to make your code readable by a green graduate? Imagine them going through it line by line. If there are no comments, then they need to understand every function call, and every library routine. They need to understand a bit about your architecture and date model.

Now imagine that every single line is commented.

In that scenario, a green programmer can read your file by reading one comment after the next. If they need more information, they can still drill into the code and get the details, but they can understand the overview just through comments.

The closer you can get to that, the better.

Don’t listen to the arguments against thorough commenting habits. Just point the detractors here.

Why are Side Effects Bad?

Side effects are any observable change to the state of an object. Some people might qualify this by saying that side effects are implicit or unintended changes to state.

Mutator methods, or setters, which are designed to change the state of an object, should have side effects. Accessor methods, or getters, should not have side effects. Other methods should generally try to avoid changing state beyond what is necessary for the intended task.

Why are these guidelines best practices though? What makes side effects so bad? Students have asked me this question many times, and I’ve worked with many experienced programmers who don’t seem to understand why minimizing side effects is a good goal.

For example, I recently commented out a block of my peer’s code because it had detrimental side effects. The code was intended to add color highlighting to log entries to make his debugging easier. The problem with the code was that the syntax highlighting xml was leaking into our save files. He was applying the highlight to a key, then using that key both in the log and in the save file. Worse still, he wrote this code so that it only occurred on some platforms. When I was debugging a cross platform feature, I got very unpredictable behavior and ultimately traced it back to this block.

This is an example where code was intended for one purpose, but it also did something else. That something else is the side effect, and you can see how it caused problems for other developers. Since his change was undocumented and uncommented, I spent hours tracking it down. As a team, we lost significant productivity due to a side effect.

Side effects are bad because they make a code base less agile. Side effects cause bugs that are difficult to find, and lead to code that is more difficult to maintain.

Before I continue, let me be clear that all code style guidelines should be broken sometimes. For each situation, a guideline or design pattern may be better or worse, and I recognize that we are always working in shades of gray.

Generally, a block of code should be written for one purpose. If it is a method, then it should do one thing. If another thing needs to be done with an object, then that should be encapsulated in another method.

Here’s a hypothetical example that I’ve seen played out hundreds of times in my career.

A class needs to do task X. A programmer may write a method to do task X, but he accidentally includes logic that also does task Y. Later, he may see that he needs to do task Y all alone. So he writes a method to do task Y. That’s where the problem is compounded.

Later still, the definition of task Y changes. So another programmer has to rewrite task Y. He goes to the class, changes the method for task Y alone, does a few quick tests, and proceeds on his merry way.

Then mysterious bugs start occurring. QA can’t really track them down to one thing because they only occur sporadically after task Y. Finally, it takes many man-hours to remove task Y from the method for task X.

In this example, the side effect led to code duplication, which led to trouble when updating the code, which led to bugs that cost many hours to track down. The fewer side effects you introduce, the easier your code will be to maintain.

These two examples show how side effects can derail development and why they are so inimical. We all write code with side effect occasionally, but it’s our job to figure out how to do it in a way that doesn’t make the code more difficult to maintain.

Make Explosive Soundscapes with Circular Sound

I’ve just finished work on a new musical instrument for Android devices. It’s called Circular Sound, and it’s aimed at people who like noise.

Circular Sound is similar to my other recent mobile instruments in that it combines a sampler with custom digital signal processing, and a unique interface. Sounds can be loaded from a configurable directory on the device, or you can play around with the default sounds, which are from Then they are loaded into spheres that are arranged in a circle on the left half of the screen. The left half of the screen is the source audio mixer, while the right half is used to control effects. The effects include waveshaping, granulation, delay, and modulation.

The goal of Circular Sound is to give a simple access point into generating various types of noise that is related in some way to the source sounds provided by the user.

Download it for free on Google Play and shoot me a comment to let me know if you make something cool with it!

Drunk Paintings

These images were not created while I was drinking. Rather, they were created using an algorithm that combines several random walks, which are also known as drunk walks.

Poppy field and sky



Strange Trasmissions, a Bundle of Weird Massive Presets


Massive is a Native Instruments synthesizer that is strongly associated with dubstep, and with modern electronica in general. As a commercial product, it is primarily designed for use as a musical instrument within the setting of pitched, tonal music. Still, I’ve been curious about how far I can push Massive to create strange, other-worldly synth sounds. For the past few weeks I’ve been creating Massive presets that take Massive out of its usual setting, and apply it to the task of abstract noise and soundscape generation. The bundle is called Strange Transmissions, and it shows the versatility of the Massive synthesizer.

Download Strange_Transmissions, a pack of 20 new presets for the Massive synthesizer.

Disconnected, Algorithmic Sound Collages from Web API

I’m pleased to announce the release of Disconnected, and album of algorithmic sound collages generated by pulling sounds from the web.

I prefer to call this album semi-algorithmic because some of the music is purely software-generated, while other pieces are a collaboration between the software and myself. Tracks four and six are purely algorithmic, while the other tracks are a mix of software-generated material and more traditionally composed material.


The software used in the sound collage pieces (1, 3, 4, 6) was inspired by Melissa Schilling’s Small World Network Model of Cognitive Insight. Her theory essentially says that moments of cognitive insight, or creativity, occur whenever a connection is made between previously distantly related ideas. In graph theory, these types of connections are called bridges, and they have the effect of bringing entire neighborhoods of ideas closer together.

I applied Schilling’s theory to sounds from My software searches for neighborhoods of sounds that are related by aural similarity and stores them in a graph of sounds. These sounds are then connected with more distant sounds via lexical connections from These lexical connections are bridges, or moments of creativity. This process is detailed in the paper Composing with All Sound Using the FreeSound and Wordnik APIs.

Finally, these sound graphs must be activated to generate sound collages. I used a modified boids algorithm to allow a swarm to move over the sound graph. Sounds were triggered whenever the population on a vertex surpassed a threshold.

Disconnected is available for download from Xylem Records.


Cannot Connect for Solo Laptop Performer

“Cannot Connect” is a problem for both computers and for people. When dealing with technology, we receive this message when we try to use something new. For people, this can be a problem in every sort of relationship.

The keyboard is a tool that people use every day to try to connect with other people. Through blogs, tweets, prose and poetry, we try to engage other humans through our work at the keyboard.

In this piece, the performer attempts to connect to both the computer and the audience through the keyboard. The software presents a randomized electronic instrument each time it is started. It selects from a palette of samples, synthesizers and signal processing effects. The performer must feel out the new performance environment and use it to connect to the audience by typing free association verse.

Becoming Live – A Swarm-Controlled Sampler

Becoming is an algorithmic composition program written in java, that builds upon some of John Cage’s frequently employed compositional processes. Cage often used the idea of a “gamut” in his compositions. A gamut could be a collection of musical fragments, or a collection of sounds, or a collection of instruments. Often, he would arrange the gamut visually on a graph, then use that graph to piece together the final output of a piece. Early in his career, he often used a set of rules or equations to determine how the output would relate to the graph. Around 1949, during the composition of the piano concerto, he began using chance to decide how music would be assembled from the graph and gamut.

In Becoming, I directly borrow Cage’s gamut and graph concepts; however, the software assembles music using concepts from the AI subfield of swarm intelligence. I place a number of agents on the graph and, rather than dictating their motions from a top-down rule-based approach, the music grows in a bottom-up fashion based on local decisions made by each agent. Each agent has preferences that determine their movement around the graph. These values dictate how likely the agent is to move toward food, how likely the agent is to move toward the swarm, and how likely the performer is to avoid the predator.