美文网首页
Unity杂文——AssetBundle自动标记

Unity杂文——AssetBundle自动标记

作者: 脸白 | 来源:发表于2023-09-28 20:40 被阅读0次

    原文地址

    参考文章

    目的

    当我们想把资源打包成AB的时候,需要把资源一个一个标记AB名字,其实大多数名字都是资源名字,如果资源一旦很多,就需要花费大量的时间,为了提高开发效率,我们肯定希望能把需要热更的资源一键标记资源名字。

    思路

    自动打标记无非就是给我一个资源路径,我通过这个路径将里面的所有的资源文件遍历一遍,然后通过 AssetImporter 这个 API 设置每个文件的 assetbundleName 和 assetBundleVariant 属性,当然在设置属性的时候提前分好类,决定将哪些资源放到一个 AssetBundle 包内。然后记录一下要打多少个 AssetBundle 包,以及该包所在的目录,方便以后查找加载。
    废话不多说,直接上代码:

     # region 自动做标记
    [MenuItem("AssetBundle/Set AssetBundle Lables" ,false , 100)]
    public static void SetAssetBundleLables()
    {
        //移除掉所有没有使用的标记
        AssetDatabase.RemoveUnusedAssetBundleNames();
        string assetDirectory = "Assets/Res";
        DirectoryInfo directoryInfo = new DirectoryInfo(assetDirectory);
        DirectoryInfo[] scenesDirectories = directoryInfo.GetDirectories();
        foreach (var tempDir in scenesDirectories)
        {
            string sceneDirectory = assetDirectory + "/" + tempDir.Name;
            DirectoryInfo sceneDirectoryInfo = new DirectoryInfo(sceneDirectory);
            if (sceneDirectoryInfo == null)
            {
                Debug.Log(sceneDirectoryInfo + "不存在");
                return;
            }
            else
            {
                Dictionary<string , string> namePathDictionary = new Dictionary<string, string>();
                int index = sceneDirectory.LastIndexOf("/");
                string sceneName = sceneDirectory.Substring(index + 1);
                OnSceneFileSystemInfo(sceneDirectoryInfo , sceneName , namePathDictionary);
                OnWriteConfig(sceneName , namePathDictionary);
            }
        }
        AssetDatabase.Refresh();
        Debug.Log("设置标记成功...");
    }
    
    /// <summary>
    /// 记录配置文件
    /// </summary>
    /// <param name="sceneDirectory"></param>
    /// <param name="namePathDictionary"></param>
    private static void OnWriteConfig(string sceneName , Dictionary<string , string> namePathDictionary)
    {
        string path = Application.dataPath + "/AssetBundles/" + sceneName ;
    
        if (!Directory.Exists(path)) Directory.CreateDirectory(path);
        Debug.Log(path);
        using (FileStream fs = new FileStream(path + "/Record.txt", FileMode.OpenOrCreate , FileAccess.Write))
        {
            using (StreamWriter sw = new StreamWriter(fs))
            {
                sw.WriteLine(namePathDictionary.Count);
                foreach (KeyValuePair<string , string> kv in namePathDictionary)
                {
                    Debug.Log(kv.Value);
                    sw.WriteLine(kv.Key+"/"+kv.Value);
                }
            }
        }
    }
    
    private static void OnSceneFileSystemInfo(FileSystemInfo fileSystemInfo , string sceneNama , Dictionary<string, string> namePathDictionary)
    {
        if (!fileSystemInfo.Exists)
        {
            Debug.Log(fileSystemInfo + "不存在");
            return;
        }
        DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo;
    
        FileSystemInfo[] fileSystemInfos = directoryInfo.GetFileSystemInfos();
        foreach (var systemInfo in fileSystemInfos)
        {
            FileInfo fileInfo = systemInfo as FileInfo;
            if (fileInfo == null)
            {
                OnSceneFileSystemInfo(systemInfo, sceneNama , namePathDictionary);
            }
            else
            {
                SetLables(fileInfo, sceneNama , namePathDictionary);
            }
        }
    }
    /// <summary>
    /// 修改资源 assetbundle lables
    /// </summary>
    private static void SetLables(FileInfo fileInfo , string sceneName , Dictionary<string, string> namePathDictionary)
    {
        if(fileInfo.Extension == ".meta")return;
        string bundleName = GetBundleName(fileInfo , sceneName);
        int index = fileInfo.FullName.IndexOf("Assets");
        string assetPath = fileInfo.FullName.Substring(index);
        AssetImporter assetImporter = AssetImporter.GetAtPath(assetPath);
        assetImporter.assetBundleName = bundleName;
        if (fileInfo.Extension == ".unity")
            assetImporter.assetBundleVariant = "u3d";
        else
            assetImporter.assetBundleVariant = "assetbundle";
        string folderName;
        if (bundleName.Contains("/"))
            folderName = bundleName.Split('/')[1];
        else
            folderName = bundleName;
        string bundlePath = assetImporter.assetBundleName + "." + assetImporter.assetBundleVariant;
        if (!namePathDictionary.ContainsKey(folderName))
            namePathDictionary.Add(folderName, bundlePath);
    }
    
    private static string GetBundleName(FileInfo fileInfo, string sceneName)
    {
        string path = fileInfo.FullName;
        int index = path.IndexOf(sceneName) + sceneName.Length;
        string bundlePath = path.Substring(index + 1);
        bundlePath = bundlePath.Replace(@"\", "/");
        if (bundlePath.Contains("/"))
        {
            string[] tmp = bundlePath.Split('/');
    
            return sceneName + "/" + tmp[0];
        }
        return sceneName;
    }
    
    #endregion
    

    一键打包

    一键打包
    根据刚才我们设置好的标记,Unity 就可以识别到我们想要打包的资源,官方有个打包 AssetBundle 的插件( AssetBundle Browser ),你可以用那款插件打包。
    作自己也写了一个但是不是很好,这个东西可以用官方的代替。也可以根据自己的需求改一下。我这里选择的压缩方式是不压缩( BuildAssetBundleOptions.None 这个选项)。

    #region 打包
    static void BuildAssetBundles(string outPath , BuildTarget target)
    {
        if (!Directory.Exists(outPath)) Directory.CreateDirectory(outPath);
        BuildPipeline.BuildAssetBundles(outPath, BuildAssetBundleOptions.None, target);
    }
    
    [MenuItem("AssetBundle/CreateAndroidAssetBundles", false, 200)]
    public static void BuildAndroidAssetBundles()
    {
        string outPath = "Assets/AssetBundles/Android";
        BuildAssetBundles(outPath , BuildTarget.Android);
    }
    
    [MenuItem("AssetBundle/CreateIOSAssetBundles", false, 201)]
    public static void BuildIOSAssetBundles()
    {
        string outPath = "Assets/AssetBundles/IOS";
        BuildAssetBundles(outPath, BuildTarget.iOS);
    }
    
    [MenuItem("AssetBundle/CreateStandaloneWindows64AssetBundles", false, 202)]
    public static void BuildStandaloneWindows64AssetBundles()
    {
        string outPath = "Assets/AssetBundles/StandaloneWindows64";
        BuildAssetBundles(outPath, BuildTarget.StandaloneWindows64);
    }
    #endregion
    

    一键删除

    把目标路径删除掉就 OK 了。

    #region 一键删除
    [MenuItem("AssetBundle/Delete All")]
    static void DeletAssetBundles()
    {
        string outPuth = "Assets/AssetBundles";
        Directory .Delete(outPuth , true);
        File.Delete(outPuth+ ".meta");
        AssetDatabase.Refresh();
    }
    #endregion

    相关文章

      网友评论

          本文标题:Unity杂文——AssetBundle自动标记

          本文链接:https://www.haomeiwen.com/subject/sorkbdtx.html