0
\$\begingroup\$

I am working on the asset bundle method, i know how to use the asset bundle for untiy 4.x series but i am trying to do this in unity5. I heard in unity 5 is more compatibility to do. I searched in youtube and google but i didnt get the proper tutorial to how to use that. So please suggest me or provide some tutorial to do this.

Thanks in Advance.

\$\endgroup\$
3
\$\begingroup\$

So, Unity 5 has changed asset bundles quite a bit from what I can see(never used them in 4). In Unity 4, you had to push and pop asset bundle dependencies and gather a list of assets that will go into your bundle.

Unity 5 provides some editor support for asset bundles. Basically every asset that has an AssetImporter can be assigned an asset bundle using the editor. There's a small UI that helps you create new asset bundle names and assign them and their variants to an asset. First you select the asset in the editor, then at the very bottom of the inspector you should see where you can assign asset bundles. The UI is pretty self explanatory and pretty much the only thing about asset bundles in 5 that's decently documented, so I'll talk about the more complicated stuff.

So, once you assign all the assets you want an asset bundle, how do you build them? Well we have to do this in an editor script still:

public class BuildAssetBundles
{
    [MenuItem( "Assets/Build Asset Bundles" )]
    public static void ExecBuildAssetBundles()
    {
        BuildPipeline.BuildAssetBundles( "Path/To/Output/Folder", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows );
    }
}

And that's it. This will build all your bundles tagged in the editor and put each one's dependencies in the bundle with the same name as the output folder. We can specify some options here such as no compression, force rebuilds every time etc. The last parameter we give is the target platform. You should build asset bundles for each platform you release on. Only asset bundles that have changed are rebuilt when calling this method.

That's fine, but what if you want to set asset bundles in scripts? You have a couple of options:

public class BuildAssetBundles
{
            [MenuItem( "Assets/Build Asset Bundles" )]
    public static void ExecBuildAssetBundles()
    {
        var assetPath        = SomeMethodThatGetsAnAssetIWant();
        var assetImporter    = AssetImporter.GetAtPath( assetPath );

        // This will set the same tag we can edit through the editor.
        assetImporter.assetBundleName = "MyAssetBundleName"; 

        // Build all bundles with a valid assetBundleName on their importer.
        BuildPipeline.BuildAssetBundles( "Path/To/Output/Folder", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows );
    }
}

So this basically does what we did before except now we're changing our asset's bundle in code rather than the editor. This can be useful, but maybe not the best solution depending on what you're going for. Another option is the AssetBundleBuild struct that Unity provides:

public struct AssetBundleBuild
{
    public string     assetBundleName;
    public string     assetBundleVariant;
    public string[]   assetNames;
}

Using this data structure we can create asset bundles entirely in code:

var build = new AssetBundleBuild();
build.assetBundleName = "MyAssetBundle";

// NOTE: These must be paths to your assets relative to the project root. 
// This will usually be one level above your assets folder.
build.assetNames      = new string[]{ "My", "Asset", "Paths" };

There we go. It's a bit annoying we have to specify paths instead of UnityEngine.Object references, but besides that it's pretty easy. So, how do we build this? We can't use the method we used before because that's for editor asset bundles. We can use an overload of that method though:

BuildPipeline.BuildAssetBundles( "Path/To/Ouput/Folder", new AssetBundleBuild[]{ My, AssetBundle, Build, Structs }, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows );

This will build our bundle structs. NOTE: dependencies will only be recorded within the same BuildAssetBundles call. This means if you use two calls to build two asset bundles, dependencies between them will not be considered. If things will have dependencies you have to build them in the same call, or make your own dependency file.

This should be enough to build your bundles. I haven't gone into too much detail regarding variants because I've never really used them. I know they're a way to have the same bundles( names and types must be identical ), but different assets. Think swapping out HD and SD UI textures without having to load different assets entirely.

Now that's done, let's load our asset bundles. All dependencies are stored in the manifest bundle. This bundle is named the same as our output folder, and is also stored in the output folder. Let's load that first:

public IEnumerator LoadAssetBundleManifest()
{
    // Let's load the manifest using the WWW class. We need to put File:// here
    // to specify that we're looking in the local file system( opposed to 
    // a server or whatever. )
    using( WWW www = new WWW( "File:///" + outputPath + "/" + outputFolderName ) )
    {
        // Wait for download to finish.
        yield return www;

        // Check for an error. Bail out if there was one.
        if( !string.IsNullOrEmpty( www.error ) )
        {
            Debug.LogError( www.error );
            yield break;
        }

        // Load the manifest object from the bundle.
        var manifest = ( AssetBundleManifest )www.assetBundle.LoadAsset( "AssetBundleManifest" );

        // This will unload the asset bundle memory. That is, unloaded 
        // objects from the asset bundle. This is probably compressed data 
        // unless you specified otherwise. If you pass true to this method, 
        // any loaded objects will also be deleted. If you don't they will 
        // remain and it'll be your responsibility to clean up after the 
        // bundle. We pass false here because we still want to use the 
        // manifest object we just loaded.
        www.assetBundle.Unload( false );
    }
}

This gives us our manifest. What does the manifest do? Well it can tell us some things about our bundle build such as what depends on what, and what bundles were actually in the build.

http://docs.unity3d.com/ScriptReference/AssetBundleManifest.html

Also, pretty importantly, it gives us an asset bundle hash. This allows us to download a bundle only when it's been updated. The bundle will then be cached and used locally. This may not be so important if you're not planning on hosting your asset bundle on a server though.

So, now let's use our manifest to load an actual bundle:

public IEnumerator LoadAssetBundle( AssetBundleManifest manifest )
{
    // Here we'll use LoadFromCacheOrDownload. We give this a URL to our
    // bundle, and a "version". We can use the bundle hash in the manifest
    // to specify a version. If our bundle( and therefore version ) change,
    // we will download the updated version instead of loading from the cache.
    using( WWW www = WWW.LoadFromCacheOrDownload( "File:///" + absoluteBundlePath, manifest.GetAssetBundleHash( assetBundleName ) ) )
    {

        // Same as the manifest.
        yield return www;
        if( string.IsNullOrEmpty( www.error ) )
        {
            Debug.LogError( www.error );
            yield break;
        }

        // Here's our AssetBundle object.
        var bundle = www.assetBundle;

        // From here we can load assets sync or async.
        var loadedObjects = bundle.LoadAllAssets<MyType>();

        // Or...
        var request = bundle.LoadallAssetsAsync();
        yield return request;
        var loadedAsyncObjects = request.allAssets;

        // Clean up the compressed data:
        bundle.Unload( false );

       // Dispose of objects correctly when you're done with them. I'm not
       // quite sure how to explicitly dispose of them, but removing all
       // references to objects and calling Resources.UnloadUnusedAssets
       // works.
    }
}

That's how you load objects from asset bundles. There's a bug in Unity right now( 5.1 ) that will crash the application, even in the editor, on occasions if you use LoadAllAssetsAsync. You can use the manifest to get dependencies between bundles and load them in the correct order. I've heard that Unity automatically loads bundle dependencies, but in my experience this does not happen.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.