Unity AssetBundle打包工具示例详解

 更新时间:2021年10月14日 08:30:38   作者:小紫苏xw  
这篇文章主要介绍了Unity AssetBundle打包工具,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

Unity批量打AB包

为了资源热更新,Unity支持将所有资源打包成AssetBundle资源,存放在SteamingAssets文件夹中;

在项目发布之前,需要将所有资源打包成.ab文件,动态加载;

在项目更新时,替换.ab资源文件,即可完成热更新;

ab文件在加载时,会多一步解压缩的过程,会增加性能消耗;

打包操作属于编辑器拓展,所有脚本放在Eidtor文件夹下;

1.PathTool

根据不同平台,获取ab输出和输入路径;

不同平台的输入输出路径不相同,ios,android,windows;《Unity资源文件夹介绍》

public class PathTools
{
    // 打包AB包根路径
    public const string AB_RESOURCES = "StreamingAssets"; 
    
    // 得到 AB 资源的输入目录
    public static string GetABResourcesPath()
    {
        return Application.dataPath + "/" + AB_RESOURCES;
    }

    // 获得 AB 包输出路径
    public static string GetABOutPath()
    {
        return GetPlatformPath() + "/" + GetPlatformName();
    }
    
    //获得平台路径
    private static string GetPlatformPath()
    {
        string strReturenPlatformPath = string.Empty;

#if UNITY_STANDALONE_WIN
        strReturenPlatformPath = Application.streamingAssetsPath;
#elif UNITY_IPHONE
            strReturenPlatformPath = Application.persistentDataPath;
#elif UNITY_ANDROID
            strReturenPlatformPath = Application.persistentDataPath;
#endif
        
        return strReturenPlatformPath;
    }
    
    // 获得平台名称
    public static string GetPlatformName()
    {
        string strReturenPlatformName = string.Empty;

#if UNITY_STANDALONE_WIN
        strReturenPlatformName = "Windows";
#elif UNITY_IPHONE
            strReturenPlatformName = "IPhone";
#elif UNITY_ANDROID
            strReturenPlatformName = "Android";
#endif

        return strReturenPlatformName;
    }
    
    // 返回 WWW 下载 AB 包加载路径
    public static string GetWWWAssetBundlePath()
    {
        string strReturnWWWPath = string.Empty;

#if UNITY_STANDALONE_WIN
        strReturnWWWPath = "file://" + GetABOutPath();
#elif UNITY_IPHONE
            strReturnWWWPath = GetABOutPath() + "/Raw/";
#elif UNITY_ANDROID
            strReturnWWWPath = "jar:file://" + GetABOutPath();
#endif

        return strReturnWWWPath;
    }
}

2.CreateAB

功能:选中一个文件夹,将该文件夹中所有资源文件打包成AB文件;

主要逻辑:遍历文件夹中所有文件,是文件的生成AssetBundleBuild存在链表中统一打包,是文件夹的递归上一步操作,将所有资源文件都放在listassets链表中;

官方Api:BuildPipeline.BuildAssetBundles统一打包所有资源;

public class CreateAB : MonoBehaviour
{
    private static string abOutPath;
    private static List<AssetBundleBuild> listassets = new List<AssetBundleBuild>();
    private static List<DirectoryInfo> listfileinfo = new List<DirectoryInfo>();
    private static bool isover = false; //是否检查完成,可以打包
    static private string selectPath;

    public static bool GetState()
    {
        return isover;
    }

    public static AssetBundleBuild[] GetAssetBundleBuilds()
    {
        return listassets.ToArray();
    }

    [MenuItem("ABTools/CreatAB &_Q", false)]
    public static void CreateModelAB()
    {
        abOutPath = Application.streamingAssetsPath;

        if (!Directory.Exists(abOutPath))
            Directory.CreateDirectory(abOutPath);

        UnityEngine.Object obj = Selection.activeObject;
        selectPath = AssetDatabase.GetAssetPath(obj);
        SearchFileAssetBundleBuild(selectPath);
        
        BuildPipeline.BuildAssetBundles(abOutPath,
            CreateAB.GetAssetBundleBuilds(), BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);
        Debug.Log("AssetBundle打包完毕");
    }

    [MenuItem("ABTools/CreatAB &_Q", true)]
    public static bool CanCreatAB()
    {
        if (Selection.objects.Length > 0)
        {
            return true;
        }
        else
            return false;
    }

这里为什么会红我也不知道...

//是文件,继续向下
    public static void SearchFileAssetBundleBuild(string path) 
    {
        DirectoryInfo directory = new DirectoryInfo(@path);
        FileSystemInfo[] fileSystemInfos = directory.GetFileSystemInfos();
        listfileinfo.Clear();
        //遍历所有文件夹中所有文件
        foreach (var item in fileSystemInfos)
        {
            int idx = item.ToString().LastIndexOf(@"\");
            string name = item.ToString().Substring(idx + 1);
            //item为文件夹,添加进listfileinfo,递归调用
            if ((item as DirectoryInfo) != null)
                listfileinfo.Add(item as DirectoryInfo);
            
            //剔除meta文件,其他文件都创建AssetBundleBuild,添加进listassets;
            if (!name.Contains(".meta"))
            {
                CheckFileOrDirectoryReturnBundleName(item, path + "/" + name);
            }
        }

        if (listfileinfo.Count == 0)
            isover = true;
        else
        {
            Debug.LogError(listfileinfo.Count);
        }
    }

    //判断是文件还是文件夹
    public static string CheckFileOrDirectoryReturnBundleName(FileSystemInfo fileSystemInfo, string path) 
    {
        FileInfo fileInfo = fileSystemInfo as FileInfo;
        if (fileInfo != null)
        {
            string[] strs = path.Split('.');
            string[] dictors = strs[0].Split('/');
            string name = "";
            for (int i = 1; i < dictors.Length; i++)
            {
                if (i < dictors.Length - 1)
                {
                    name += dictors[i] + "/";
                }
                else
                {
                    name += dictors[i];
                }
            }

            string[] strName = selectPath.Split('/');
            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
            assetBundleBuild.assetBundleName = strName[strName.Length - 1];
            assetBundleBuild.assetBundleVariant = "ab";
            assetBundleBuild.assetNames = new string[] {path};
            listassets.Add(assetBundleBuild);
            return name;
        }
        else
        {
            //递归调用
            SearchFileAssetBundleBuild(path);
            return null;
        }
    }
}

3.ClearABLable

打包时每个资源会添加一个标签,如果重复打包,需要清空才可再次打包,否则会失败;

使用官方API:AssetDatabase.RemoveUnusedAssetBundleNames();

因为注释写的很详细,就不赘述了;

public class ClearABLable
{
    [MenuItem("ABTools/Remove AB Label")]
    public static void RemoveABLabel()
    {
        // 需要移除标记的根目录
        string strNeedRemoveLabelRoot = string.Empty;
        // 目录信息(场景目录信息数组,表示所有根目录下场景目录)
        DirectoryInfo[] directoryDIRArray = null;
        
        // 定义需要移除AB标签的资源的文件夹根目录
        strNeedRemoveLabelRoot = PathTools.GetABResourcesPath();   

        DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedRemoveLabelRoot);
        directoryDIRArray = dirTempInfo.GetDirectories();

        // 遍历本场景目录下所有的目录或者文件
        foreach (DirectoryInfo currentDir in directoryDIRArray)
        {
            // 递归调用方法,找到文件,则使用 AssetImporter 类,标记“包名”与 “后缀名”
            JudgeDirOrFileByRecursive(currentDir);
        }

        // 清空无用的 AB 标记
        AssetDatabase.RemoveUnusedAssetBundleNames();
        // 刷新
        AssetDatabase.Refresh();

        // 提示信息,标记包名完成
        Debug.Log("AssetBundle 本次操作移除标记完成");
    }

    /// <summary>
    /// 递归判断判断是否是目录或文件
    /// 是文件,修改 Asset Bundle 标记
    /// 是目录,则继续递归
    /// </summary>
    /// <param name="fileSystemInfo">当前文件信息(文件信息与目录信息可以相互转换)</param>
    private static void JudgeDirOrFileByRecursive(FileSystemInfo fileSystemInfo)
    {
        // 参数检查
        if (fileSystemInfo.Exists == false)
        {
            Debug.LogError("文件或者目录名称:" + fileSystemInfo + " 不存在,请检查");
            return;
        }

        // 得到当前目录下一级的文件信息集合
        DirectoryInfo directoryInfoObj = fileSystemInfo as DirectoryInfo; 
        // 文件信息转为目录信息
        FileSystemInfo[] fileSystemInfoArray = directoryInfoObj.GetFileSystemInfos();

        foreach (FileSystemInfo fileInfo in fileSystemInfoArray)
        {
            FileInfo fileInfoObj = fileInfo as FileInfo;

            // 文件类型
            if (fileInfoObj != null)
            {
                // 修改此文件的 AssetBundle 标签
                RemoveFileABLabel(fileInfoObj);
            }
            // 目录类型
            else
            {
                // 如果是目录,则递归调用
                JudgeDirOrFileByRecursive(fileInfo);
            }
        }
    }

    /// <summary>
    /// 给文件移除 Asset Bundle 标记
    /// </summary>
    /// <param name="fileInfoObj">文件(文件信息)</param>
    static void RemoveFileABLabel(FileInfo fileInfoObj)
    {
        // AssetBundle 包名称
        string strABName = string.Empty;
        // 文件路径(相对路径)
        string strAssetFilePath = string.Empty;

        // 参数检查(*.meta 文件不做处理)
        if (fileInfoObj.Extension == ".meta")
        {
            return;
        }

        // 得到 AB 包名称
        strABName = string.Empty;
        // 获取资源文件的相对路径
        int tmpIndex = fileInfoObj.FullName.IndexOf("Assets");
        // 得到文件相对路径
        strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex); 
        
        // 给资源文件移除 AB 名称
        AssetImporter tmpImportObj = AssetImporter.GetAtPath(strAssetFilePath);
        tmpImportObj.assetBundleName = strABName;
    }
}

4.拓展

更多的时候,我们打包需要一键打包,也可能需要多个文件打成一个ab包,只需要修改一下文件逻辑即可;

打ab包本身并不复杂,对文件路径字符串的处理比较多,多Debug调试;

到此这篇关于Unity AssetBundle打包工具的文章就介绍到这了,更多相关Unity AssetBundle打包内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#静态代码织入AOP组件之Rougamo的使用详解

    C#静态代码织入AOP组件之Rougamo的使用详解

    Rougamo是一个静态代码织入的AOP组件,同为AOP组件较为常用的有Castle、Autofac、AspectCore等,下面就跟随小编一起来学习一下它的具体使用吧
    2024-01-01
  • C#实现发送手机验证码功能

    C#实现发送手机验证码功能

    之前基于c#实现手机发送验证码功能很复杂,真正做起来也就那回事,不过就是一个post请求就可以实现的东西,今天小编把思路分享到脚本之家平台,供大家参考下
    2017-06-06
  • 使用c#实现微信自动化功能

    使用c#实现微信自动化功能

    这篇文章主要介绍了使用c#实现微信自动化,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • C#直线的最小二乘法线性回归运算实例

    C#直线的最小二乘法线性回归运算实例

    这篇文章主要介绍了C#直线的最小二乘法线性回归运算方法,实例分析了给定一组点,用最小二乘法进行线性回归运算的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-08-08
  • C#实现数独解法

    C#实现数独解法

    这篇文章介绍了C#实现数独解法的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • c#实现一元二次方程求解器示例分享

    c#实现一元二次方程求解器示例分享

    这篇文章主要介绍了c#实现一元二次方程求解器示例,需要的朋友可以参考下
    2014-03-03
  • C# 6.0的属性(Property)的语法与初始值详解

    C# 6.0的属性(Property)的语法与初始值详解

    下面小编就为大家带来一篇C# 6.0的属性(Property)的语法与初始值详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • C#迭代器方法介绍

    C#迭代器方法介绍

    这篇文章主要介绍了C#迭代器方法,可以使用foreach循环语句进行的迭代的方法,称为可迭代方法,或者迭代器方法,方法操作,想了解更多内容得小伙伴可以学习下面文章内容,希望给你的学习带来帮助
    2022-03-03
  • C#中AutoResetEvent控制线程用法小结

    C#中AutoResetEvent控制线程用法小结

    本文主要来自一道面试题,由于之前对AutoResetEvent的概念比较模糊,面试题题目很简洁:两个线程交替打印0~100的奇偶数,你可以先动手试试,我主要是尝试在一个方法里面完成这个任务,需要的朋友可以参考下
    2022-07-07
  • C#编程实现发送邮件的方法(可添加附件)

    C#编程实现发送邮件的方法(可添加附件)

    这篇文章主要介绍了C#编程实现发送邮件的方法,具备添加附件的功能,涉及C#文件传输及邮件发送的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-11-11

最新评论