AssetBundle打包学习(一)

AssetBundle是Unity支持的一种资源打包方式。区别于Resources目录的打包资源,AssetBundle可以更加方便灵活的定制自己的资源组织方式,也可以支持资源更新。

AssetBundle 打包

AssetBundle打包以Object为单位,我们可以通过Untiy接口加载资源引用到的所有资源去打包,也可以对这些资源做筛选。

public static bool BuildAssetBundle(
    UnityEngine.Object[] objs, string outputPath, out uint crc) {
    crc = 0;
    return BuildPipeline.BuildAssetBundle(null, objs,outputPath, out crc,
            BuildAssetBundleOptions.ChunkBasedCompression |
            BuildAssetBundleOptions.DeterministicAssetBundle |
            BuildAssetBundleOptions.CollectDependencies,
            BuildTarget.Android);
}

public static bool BuildAssetBundle(
    string[] assetsList, string outputPath,
    out uint crc , BundleType bundleType) {
    crc = 0;

    // Load all of assets in this bundle
    List assets = new List();
    foreach (string assetPath in assetsList) {
        UnityEngine.Object[] assetsAtPath = AssetDatabase.LoadAllAssetsAtPath(assetPath);
        assets.AddRange(assetsAtPath);
    }

    // assets include some not use object, we can filter used objects to reduce bundle size
    assets = FilterObjectByType(assets, bundleType);

    if (assets.Count == 0) {
        return false;
    }

    return BuildAssetBundle(assets.ToArray(), outputPath, out crc);
}

Shader资源打包

Unity内置的Shader,并不能找到一个路径去打包,这时候我们可以直接把Shader作为Object传进去打包。

public static void BuildShaderBundle(string outputPath) {
    HashSet shaderSet = new HashSet();
    string[] files = Directory.GetFiles("Assets/", "*.mat", SearchOption.AllDirectories);
    for (int i = 0; i < files.Length; ++i) {
        Material material = AssetDatabase.LoadAssetAtPath(files[i]);
        if (material != null && material.shader != null &&
            !shaderSet.Contains(material.shader.name)) {
                shaderSet.Add(material.shader.name);
        }
    }

    List shaderObjects = new List();
    foreach (string shaderName in shaderSet) {
        shaderObjects.Add(Shader.Find(shaderName));
    }

    if (shaderObjects.Count == 0) return;

    uint crc = 0;
    BuildAssetBundle(shaderObjects.ToArray(), outputPath, out crc);
}

公用资源打包

考虑到不同的资源可能引用到相同的资源,比如两个模型引用了相同的贴图,如果这时候把两个模型打成二个AssetBundle,那这张贴图会被分别打到两个AssetBundle里。
Unity提供里PushAssetDependencies和PopAssetDependencies来管理打包,同层之间的资源也是依赖的(先打的包有的,后面包就不会再打了),这里要比较小心不然依赖关系容易乱。
之前提到的Shader资源打包,可以做为共享包放在最顶层打包,这样Shader就只有一份了。

public static void BuildAllBundles(List commonTexture, List modelList) {
    BuildPipeline.PushAssetDependencies();
    BuildShaderBundle("Bundle/Shader.assetbundle");

    foreach (string path in commonTexture) {
        BuildAssetBundle(path);
    }

    foreach (string path in modelList) {
        BuildPipeline.PushAssetDependencies();
        BuildAssetBundle(path);
        BuildPipeline.PopAssetDependencies();
    }

    BuildPipeline.PopAssetDependencies();
}

Unity 5 AssetBundle打包

Unity 5简化了打包过程,只需要设置BundleName,然后Build即可。
Unity 5支持在Inspect界面给每个资源设定BundleName,比起代码设置多了一种管理途径。

public static void BuildAssetBuilds(string[] assetsPath) {
    for (int i = 0; i < assetsPath.Length; ++i) {
        AssetImporter asset = AssetImporter.GetAtPath(assetsPath[i]);
        asset.assetBundleName = Path.GetFileNameWithoutExtension(assetsPath[i]);
        asset.assetBundleVariant = "assetbundle";
        AssetDatabase.ImportAsset(assetsPath[i]);
    }
    AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);

    BuildPipeline.BuildAssetBundles("Bundles");
}

总结

Unity提供了丰富的接口便于我们去构建AssetBundle,不过构建大小合理依拉关系清晰的AssetBundle还需要下较大的功夫去分析资源之间的依赖关系。
对比Unity 5新的打包方式,可以发现老接口可以更加精确的控制资源打包的力度,而且对于类似Unity内置Shader这种无路径内置对象,5只能通过替换Shader为本地的有路径Shader来做,不够灵活

AssetBundle压缩格式介绍

你可能感兴趣的:(AssetBundle打包学习(一))