首页 > 其他分享 >AsssetBundle打包(一)

AsssetBundle打包(一)

时间:2023-07-24 14:24:02浏览次数:40  
标签:AsssetBundle string AssetDatabase static path public 打包 name

先建立一个需要打包的配置文件(方便打包路径的修改)

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


[CreateAssetMenu(fileName = "ABConfig",menuName = "CreatABConfig", order = 0)]
public class ABConfig : ScriptableObject
{
    //单个文件所在文件夹路径,遍历所有Prefab,保证名字唯一性
    public List<string> m_AllPrefabPath = new List<string>();//预制体目录
    public List<FileDirABName> m_AllFileDirAB = new List<FileDirABName>();//资源文件目录

    [System.Serializable]
    public struct FileDirABName 
    {
        public string ABName;
        public string Path;
    }
}

在项目中生成一个配置文件

 手动输入配置

 之后开始写打包工具需要写在Editor文件夹下,没有Editor文件夹要自己创建一个。写一个BundleEditor的类,它要对资源,和预制体,AB包文件,进行处理。还需要对文件进行存储,以及读取配置文件。

所以它至少需要5条属性

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

public class BundleEditor
{
    //打包路径
    public static string m_assetBundlePath = Application.streamingAssetsPath;
   //配置文件路径 
   public static string ABCONFIGPATH = "Assets/Editor/Build/ABConfig.asset";
    //所有路径目录key:name, value:path
    public static Dictionary<string, string> m_AllFileDir = new Dictionary<string, string>();
    //所有AB文件
    public static List<string> m_AllFileAB = new List<string>();
    //预制体资源key:name, value:path
    public static Dictionary<string, List<string>> m_allABPrefabDir = new Dictionary<string, List<string>>();
}

预制体的Value用List来存储,用来存储依赖资源,依赖的资源都放在同一图集文件下 接下来建立我们的Build方法

[MenuItem("Tools/打包")]
    public static void Build() 
    {
        //读取配置文件路径
        ABConfig aBConfig = AssetDatabase.LoadAssetAtPath<ABConfig>(ABCONFIGPATH);
        //创建打包文件目录
        if (!Directory.Exists(m_assetBundlePath)) 
            Directory.CreateDirectory(m_assetBundlePath);
     }

 

接下来对abConfig里的资源文件进行遍历对比防止配置重复

    [MenuItem("Tools/打包")]
    public static void Build() 
    {
        //读取配置文件路径
        ABConfig aBConfig = AssetDatabase.LoadAssetAtPath<ABConfig>(ABCONFIGPATH);
        //创建打包文件目录
        if (!Directory.Exists(m_assetBundlePath)) 
            Directory.CreateDirectory(m_assetBundlePath);

     foreach (ABConfig.FileDirABName filDir in aBConfig.m_AllFileDirAB)
            {
                Debug.Log(filDir.ABName);
                Debug.Log(filDir.Path);

                if (m_AllFileDir.ContainsKey(filDir.ABName))
                {
                    Debug.LogError("配置重复");
                }
                else 
                {
                    m_AllFileDir.Add(filDir.ABName, filDir.Path);
                    m_AllFileAB.Add(filDir.Path);
                }
            }
    }

之后对预制体配置路径进行预制体读取以及依赖读取

     tring[] allStr = AssetDatabase.FindAssets("t:Prefab", aBConfig.m_AllPrefabPath.ToArray());//读取配置路径下的所有Prefab
        for (int i = 0; i < allStr.Length; i++) 
        {
            string path = AssetDatabase.GUIDToAssetPath(allStr[i]);//获得路径
            EditorUtility.DisplayProgressBar("查找Prefab", "Prefab" + path, i * 1.0f / allStr.Length);
           
            if (!ContainAllFileAB(path)) 
            {
                GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
                string[] allDepend = AssetDatabase.GetDependencies(path);
                List<string> allDependPath = new List<string>();

                for (int j = 0; j < allDepend.Length; j++) 
                {
                    if (!ContainAllFileAB(allDepend[j]) && !allDepend[j].EndsWith(".cs")) 
                    {
                        m_AllFileAB.Add(allDepend[j]);
                        allDependPath.Add(allDepend[j]);
                    }
                }
                if (m_allABPrefabDir.ContainsKey(obj.name))
                {
                    Debug.LogError("存在相同Prefab" + obj.name);
                }
                else 
                {
                    m_allABPrefabDir.Add(obj.name, allDependPath);
                }
            }
        }
    /// <summary>
    /// 是否包含在已经有的AB包里
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    static bool ContainAllFileAB(string path) 
    {
        for (int i = 0; i < m_AllFileAB.Count; i++)
        {
            if (path == m_AllFileAB[i] || path.Contains(m_AllFileAB[i]))
                return true;
        }

        return false;
    }

之后为得到的文件资源和预制体资源设置AsssetBundle名

     foreach (string name in m_AllFileDir.Keys) 
        {
            SetABName(name, m_AllFileDir[name]);
        }

        foreach (string name in m_allABPrefabDir.Keys) 
        {
            SetABName(name, m_allABPrefabDir[name]);
        }
 //设置AsssetBundle名
static void SetABName(string name, string path) { AssetImporter assetImporter = AssetImporter.GetAtPath(path); if (assetImporter == null) { Debug.LogError("文件不存在" + path); } else { assetImporter.assetBundleName = name; } } static void SetABName(string name, List<string> paths) { for (int i = 0; i < paths.Count; i++) { SetABName(name, paths[i]); } }

再执行打包方法

static void BuildAssetBundle() 
    {
        string[] allBundles = AssetDatabase.GetAllAssetBundleNames();
        //key全路径,value包名
        Dictionary<string, string> resPathDic = new Dictionary<string, string>();

        for (int i = 0; i < allBundles.Length; i++) 
        {
            string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]);

            for (int j = 0; j < allBundlePath.Length; j++) 
            {
                if (allBundlePath[j].EndsWith(".cs"))
                    continue;
                resPathDic.Add(allBundlePath[j], allBundles[i]);
            }
        }

        DeleteAB();
        //生成ab配置表(后面写)

        //打包使用LZ4压缩格式,目标平台当前用户激活的平台,打场景得不压缩,场景压缩后会加载不出来
        BuildPipeline.BuildAssetBundles(m_assetBundlePath, BuildAssetBundleOptions.ChunkBasedCompression
            , EditorUserBuildSettings.activeBuildTarget);
    }
    /// <summary>
    /// 删掉冗余的AB包
    /// </summary>
    static void DeleteAB() 
    {
        string[] allBundlesName = AssetDatabase.GetAllAssetBundleNames();
        DirectoryInfo direction = new DirectoryInfo(m_assetBundlePath);
        FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);

        for (int i = 0; i < files.Length; i++) 
        {
            if (ConatinABName(files[i].Name, allBundlesName) || files[i].Name.EndsWith(".meta"))
            {
                continue;
            }
            else 
            {
                Debug.Log("已发生变化AB包" + files[i].Name);
                if (File.Exists(files[i].FullName)) 
                {
                    File.Delete(files[i].FullName);
                }
            }
        }
    }

最后整理细节

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

public class BundleEditor
{
    public static string m_assetBundlePath = Application.streamingAssetsPath;
    public static string ABCONFIGPATH = "Assets/Editor/Build/ABConfig.asset";
    //所有路径目录value:name,path
    public static Dictionary<string, string> m_AllFileDir = new Dictionary<string, string>();
    public static List<string> m_AllFileAB = new List<string>();
    //预制体资源目录value:name,path
    public static Dictionary<string, List<string>> m_allABPrefabDir = new Dictionary<string, List<string>>();

    [MenuItem("Tools/打包")]
    public static void Build() 
    {
        m_AllFileDir.Clear();
        m_AllFileAB.Clear();
        m_allABPrefabDir.Clear();
        ClearABName();
        //读取配置文件路径
        ABConfig aBConfig = AssetDatabase.LoadAssetAtPath<ABConfig>(ABCONFIGPATH);

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

        foreach (ABConfig.FileDirABName filDir in aBConfig.m_AllFileDirAB)
        {
            Debug.Log(filDir.ABName);
            Debug.Log(filDir.Path);

            if (m_AllFileDir.ContainsKey(filDir.ABName))
            {
                Debug.LogError("配置重复");
            }
            else 
            {
                m_AllFileDir.Add(filDir.ABName, filDir.Path);
                m_AllFileAB.Add(filDir.Path);
            }
        }

        string[] allStr = AssetDatabase.FindAssets("t:Prefab", aBConfig.m_AllPrefabPath.ToArray());

        for (int i = 0; i < allStr.Length; i++) 
        {
            string path = AssetDatabase.GUIDToAssetPath(allStr[i]);
            EditorUtility.DisplayProgressBar("查找Prefab", "Prefab" + path, i * 1.0f / allStr.Length);
           
            if (!ContainAllFileAB(path)) 
            {
                GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
                string[] allDepend = AssetDatabase.GetDependencies(path);
                List<string> allDependPath = new List<string>();

                for (int j = 0; j < allDepend.Length; j++) 
                {
                    if (!ContainAllFileAB(allDepend[j]) && !allDepend[j].EndsWith(".cs")) 
                    {
                        m_AllFileAB.Add(allDepend[j]);
                        allDependPath.Add(allDepend[j]);
                    }
                }
                if (m_allABPrefabDir.ContainsKey(obj.name))
                {
                    Debug.LogError("存在相同Prefab" + obj.name);
                }
                else 
                {
                    m_allABPrefabDir.Add(obj.name, allDependPath);
                }
            }
        }

        foreach (string name in m_AllFileDir.Keys) 
        {
            SetABName(name, m_AllFileDir[name]);
        }

        foreach (string name in m_allABPrefabDir.Keys) 
        {
            SetABName(name, m_allABPrefabDir[name]);
        }

        BuildAssetBundle();
       

        AssetDatabase.Refresh();
        EditorUtility.ClearProgressBar();
    }

    static void SetABName(string name, string path) 
    {
        AssetImporter assetImporter = AssetImporter.GetAtPath(path);

        if (assetImporter == null)
        {
            Debug.LogError("文件不存在" + path);
        }
        else 
        {
            assetImporter.assetBundleName = name;
        }
    }

    static void SetABName(string name, List<string> paths) 
    {
        for (int i = 0; i < paths.Count; i++) 
        {
            SetABName(name, paths[i]);
        }
    }

    static bool ConatinABName(string name, string[] strs) 
    {
        for (int i = 0; i < strs.Length; i++) 
        {
            if (name == strs[i])
                return true;
        }

        return false;
    }

    /// <summary>
    /// 是否包含在已经有的AB包里
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    static bool ContainAllFileAB(string path) 
    {
        for (int i = 0; i < m_AllFileAB.Count; i++)
        {
            if (path == m_AllFileAB[i] || path.Contains(m_AllFileAB[i]))
                return true;
        }

        return false;
    }

    static void BuildAssetBundle() 
    {
        string[] allBundles = AssetDatabase.GetAllAssetBundleNames();
        //key全路径,value包名
        Dictionary<string, string> resPathDic = new Dictionary<string, string>();

        for (int i = 0; i < allBundles.Length; i++) 
        {
            string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]);

            for (int j = 0; j < allBundlePath.Length; j++) 
            {
                if (allBundlePath[j].EndsWith(".cs"))
                    continue;
                resPathDic.Add(allBundlePath[j], allBundles[i]);
            }
        }

        DeleteAB();
        //生成ab配置表(后面写)

        //打包
        BuildPipeline.BuildAssetBundles(m_assetBundlePath, BuildAssetBundleOptions.ChunkBasedCompression
            , EditorUserBuildSettings.activeBuildTarget);
    }

    private static void ClearABName() 
    {
        string[] oldABName = AssetDatabase.GetAllAssetBundleNames();

        for (int i = 0; i < oldABName.Length; i++)
        {
            AssetDatabase.RemoveAssetBundleName(oldABName[i], true);
            EditorUtility.DisplayProgressBar("清除AB包名", oldABName[i].ToString(), i * 1.0f / oldABName.Length);
        }
    }

    /// <summary>
    /// 删掉冗余的AB包
    /// </summary>
    static void DeleteAB() 
    {
        string[] allBundlesName = AssetDatabase.GetAllAssetBundleNames();
        DirectoryInfo direction = new DirectoryInfo(m_assetBundlePath);
        FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);

        for (int i = 0; i < files.Length; i++) 
        {
            if (ConatinABName(files[i].Name, allBundlesName) || files[i].Name.EndsWith(".meta"))
            {
                continue;
            }
            else 
            {
                Debug.Log("已发生变化AB包" + files[i].Name);
                if (File.Exists(files[i].FullName)) 
                {
                    File.Delete(files[i].FullName);
                }
            }
        }
    }
}

一的部分到此结束

 

标签:AsssetBundle,string,AssetDatabase,static,path,public,打包,name
From: https://www.cnblogs.com/jiangxiaoming/p/17576764.html

相关文章

  • UE4构建基础和实践:二、Editor打包Win&Android
    此次打包使用的是5.2版本Win包操作流程参考打包项目|UE文档设置默认地图点击创建打包文件解释&分析产物分析打开打包时设置输出目录,大概如下:可以看到大概有下面几个文件目录:-ProjectName:我的项目名是BuildTest,所以文件名为BuildTest-Engine:引擎相关目录-Bui......
  • UE4构建基础&实践:三、UAT命令打包
    序言在上一篇文章中,我们使用了Editor进行打包,提到了日志的中的打包命令和参数。这一篇中,我们将实践使用UAT和默认命令打包Android,并介绍相关参数和用法。UAT&打包命令首先给出UAT工具的运行方法和打包命令参数:UAT在引擎目录下找到Engine\Build\BatchFiles的RunUAT.bat文件......
  • UE4构建基础和实践:五、CI/CD平台自动化打包
    序言使用CI/CD平台构建(这里使用蓝盾平台)主要是通过平台脚本运行上一章的py脚本并传递参数(即把py中的参数开放给配置平台脚本配置)。Build.py重构我们需要在py脚本里面解析和设置参数importsysimportosimportgetoptdefmain(argv):ProjectName=""......
  • UE4构建基础和实践:四、使用脚本打包
    序言使用UE版本为UE5.20在实际项目中,我们常常使用自动化脚本来进行构建,它可以增加我们的生产效率,并降低人为操作带来的失误风险。BuildGraphBuildGraphUE官方提供的构建脚本系统,它可以读取对应的XML脚本实现自动化打包。BuildGraph相关的参考BuildGraph|UE文档重点是它相......
  • python打包方法
    在Python中,要编写setup.py文件,用于构建和打包你的Python项目,你可以遵循以下步骤:创建项目目录结构:首先,你需要创建项目的目录结构,包括源代码文件、资源文件等。一个常见的项目结构如下:project_name/|-project_name/|-__init__.py|-module1.py......
  • idea打包springboot项目,打包成war包,如何不把lib目录或指定jar打进去?
    1、在pom.xml文件中添加如下配置:<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration>......
  • Avalonia项目打包安装包
    Avalonia项目打包安装包要将Avalonia项目打包成安装包,你可以使用Avalonia发布工具来完成1.创建一个发布配置文件在你的Avalonia项目中,创建一个发布配置文件。在项目文件夹中创建一个名为publish.xml的文件,并添加以下内容:<?xmlversion="1.0"encoding="utf-8"?><Publ......
  • python 打包apk
    Python打包APK在移动应用开发中,Android是最流行的操作系统之一。通常,我们使用Java或Kotlin编写Android应用程序,并使用AndroidStudio进行构建。不过,如果你是Python开发者,你可能会想知道是否可以使用Python来开发Android应用程序。答案是肯定的!有很多工具可以帮助我们使用Python构......
  • windows下申请huilderX打包所需要的安卓以及ios证书以及密钥文件
    背景:HbuilderX打包app时,需要证书和密钥文件,ios包所需要的证书和密钥需要在苹果电脑上申请,如果身边没有Mac也没有关系,我们也可以在windows环境下生成一系列文件。1.生成安卓包所需要的keystore文件可以通过https://www.yunedit.com/香蕉云编,非常方便。进入后点击安卓证书生成,填写......
  • ruoyi修改打包jar名称
     ......