Unity使用AssetImporter整理资源对其进行打包

  • AssetImporter概述
  • 打包思路
  • 具体实现
  • 资源配置
  • 资源配置的信息
  • 调用生成
  • 打包
  • 打包分类
  • 按照单个文件打包
  • 按照文件夹打包
  • 打包Lua文件(特别的)
  • 使用打包方法进行打包
  • 打包调用


AssetImporter概述

AssetImporter.GetAtPath获取路径资源
static function GetAtPath (path : string) : AssetImporter

Description描述

Retrieves the asset importer for the asset at path.

通过资源路径 ,导入器重新获取资源。
简单的说,通过指定路径来导入资源。

该方法返回的是AssetImporter对象,我们通常给该对象的assetBundleName赋值为要打包的资源路径名称,这个操作实际上相当于在Unity编辑器Inspector页面中手动添加是一样的。

打包思路

这里我把要打包的所有资源统一放在同一个Res文件夹下面,Res中不同的资源类型,不同的加载时间的资源新建文件夹,按照文件夹分类(如:把通用的资源放在同一个文件夹下,UI统一放入一个文件夹,material建一个文件夹),打包时在打包配置里指定要打包的资源路径,打包类型(这里类型指的是:1.整个文件夹打一个包,2.将文件夹下单个资源都对应一个ab包)

具体实现

资源配置

[System.Serializable]
public class PackageItem
{
    public enum PackType {File,DirFiles,Dir}
    public PackType type;
    public string path;
    public string searchPattern = "*.*";
    public SearchOption searchOption;
}

效果如下:

unity的未包涵getchild unity中import package_unity的未包涵getchild

资源配置的信息

[System.Serializable]
public class PackageConfig : ScriptableObject {

    private static PackageConfig _instance;
    public  static PackageConfig instance
    {
        get
        {
            _instance = AssetDatabase.LoadAssetAtPath<PackageConfig>("Assets/Tools/Editor/PackConf.asset");
            if(_instance==null)
            {
                _instance = ScriptableObject.CreateInstance<PackageConfig>();
                AssetDatabase.CreateAsset(_instance, "Assets/Tools/Editor/PackConf.asset");
            }

            return _instance;
        }
    }

    //版本号
    [SerializeField]
    private string _version = "1.0";
    public static string version { get { return instance._version; } }

    //游戏名称
    [SerializeField]
    private string _appName = "Test";
    public static string appName { get { return instance._appName; } }


    //游戏发布的目录
    [SerializeField]
    private string _publishDir = "publish/";
    public static string publishDir { get { return instance._publishDir; } }

    //游戏web发布目录
    [SerializeField]
    private string _webPublishUrl = "http://192.168.1.27/publish/";
    public static string webPulishUrl { get { return instance._webPublishUrl; } }

    // 是否使用jit
    [SerializeField]
    private bool _luaJit = true;
    public  bool luaJit { get { return instance._luaJit; } }

    // debugBuild
    [SerializeField]
    private bool _debugBuild = true;
    public static bool debugBuild { get { return instance._debugBuild; } }

    // 自动开启
    [SerializeField]
    private bool _autoRunPlayer = false;
    public static bool autoRunPlayer { get { return instance._autoRunPlayer; } }

    [SerializeField]
    private List<PackageItem> _packItems = new List<PackageItem>();
    public  List<PackageItem> packItems { get { return instance._packItems; } }

    public static BuildOptions buildOptions
    {
        get
        {
            if(debugBuild)
            {
                BuildOptions op = BuildOptions.AllowDebugging | BuildOptions.ConnectWithProfiler | BuildOptions.Development;
                if(autoRunPlayer)
                {
                    return op | BuildOptions.AutoRunPlayer;
                }
                return op;
            }
            else
            {
                return BuildOptions.None;
            }
        }
    }
   
}

调用生成

// 各种配置文件
        [MenuItem("BuildTool/依赖打包方式/发布设定")]
        public static void open()
        {
            Selection.activeObject = PackageConfig.instance;
        }

打包

打包分类

按照单个文件打包

直接指定文件所在路径

//文件打包
    public bool PackFile(string res)
    {
        AssetImporter importer = AssetImporter.GetAtPath(res);
        if (importer == null)
        {
            Debug.LogError("Path not Exist!" + res);
            return false;
        }
        importer.assetBundleName = res + abExtens;
        return true;
    }

指定资源所在的文件夹路径,查找文件夹下的所有文件,每个文件单独一个AB包

//打包目录中所有资源
    public bool PackDirFiles(string res,string pattern,SearchOption searchOption)
    {
        string[] files = GetDirFiles(res,pattern,searchOption);
        if (files.Length == 0) return false;
        foreach(var file in files)
        {
            PackFile(file);
        }
        return true;
    }
按照文件夹打包
//目录打包
    public bool PackDir(string res,string pattern,SearchOption searchOption)
    {
        string[] files = GetDirFiles(res, pattern, searchOption);
        if (files.Length == 0) return false;
        string fn = res.Trim('/') + abDirExtens;

        foreach(var file in files)
        {
            AssetImporter impoter = AssetImporter.GetAtPath(file);
            impoter.assetBundleName = fn;
        }
        return true;
    }
//打包目录中所有资源
    public bool PackDirDir(string res,string pattern)
    {
        string[] Dirs = Directory.GetDirectories(res);
        if (Dirs.Length == 0) return false;
        foreach(var d in Dirs)
        {
            PackDir(d.Replace('\\', '/'), pattern, SearchOption.AllDirectories);
        }
        return true;
    }
打包Lua文件(特别的)

如果Lua需要使用Jit进行编译

//编译Lua到固定目录
    public void CompileLuaJit(string []src,string[]dst)
    {
        Debug.Log("Start CompileLuaJit");

#if !UNITY_EDITOR_OSX
        string workDir = Application.dataPath + "/../jit/";
        Dictionary<BUILDLUATYPE, string> build = new Dictionary<BUILDLUATYPE, string>()
        {
            { BUILDLUATYPE.WIN32,Application.dataPath+"/../jit/win/x86/luajit.exe"},
            { BUILDLUATYPE.WIN64,Application.dataPath+"/../jit/win/x64/luajit.exe"},
            { BUILDLUATYPE.GC64,Application.dataPath+"/../jit/win/gc64/luajit.exe"},
        };
        string exePath = build[buildLuaDict[_target]];
        System.Diagnostics.Process[] psList = new System.Diagnostics.Process[src.Length];
#endif
        for(int i=0;i<src.Length;i++)
        {
            string srcLua = Application.dataPath + "/../" + src[i];
            string dstLua = Application.dataPath + "/../" + dst[i];
            string cmd = " -b " + srcLua + " " + dstLua;

            psList[i] = ProcessHelper.StartProcess(exePath,cmd,workDir);

        }

#if !UNITY_EDITOR_OSX
        foreach(var ps in psList)
        {
            if(ps!=null&&!ps.HasExited)
            {
                ps.WaitForExit();
            }
        }
#endif
    }

编译的过程需要使用Process调起进程exe执行编译指令

public class ProcessHelper {

    public static Process StartProcess(string command,string parm,string workDir="")
    {
        return StartProcess(command, parm, workDir, DataReceived, ErrorReceived);
    }
    public static Process StartProcess(string command, string parm, string workDir, DataReceivedEventHandler dataReceived, DataReceivedEventHandler errorReceive)
    {
        Process ps = new Process()
        {
            StartInfo =
            {
                FileName=command,
                Arguments=parm,
                CreateNoWindow=true,
                UseShellExecute=false,
                RedirectStandardOutput=true,
                RedirectStandardError=true,
                WorkingDirectory=workDir
            }
        };
        ps.OutputDataReceived += DataReceived;
        ps.ErrorDataReceived += ErrorReceived;
        ps.Start();
        ps.BeginOutputReadLine();
        ps.BeginErrorReadLine();
        return ps;
    }
    
    private static void DataReceived(object sender,DataReceivedEventArgs eventArgs)
    {
        if (null != eventArgs.Data) UnityEngine.Debug.Log(eventArgs.Data);
    }
    private static void ErrorReceived(object sender,DataReceivedEventArgs eventArgs)
    {
        if(null !=eventArgs.Data) UnityEngine.Debug.Log(eventArgs.Data);
    }
}

打包lua到 "Assets/Res/Lua/"路径下

//打包Lua目录
    public bool PackLuaDir(string res,bool useJit=true)
    {
        string fixLuaDIr = "Assets/Res/Lua/";
        AssetDatabase.DeleteAsset(fixLuaDIr);
        var files = Directory.GetFiles(res, "*.lua", SearchOption.AllDirectories);
        var dests = new string[files.Length];

        for(int i=0;i<files.Length;i++)
        {
            string file = files[i].Replace('\\', '/');
            string dst = "Assets/Res/" + file;
            string dstName = dst.Substring(0, dst.Length - 3) + "bytes"; //lua后缀改为bytes后缀

            string destDir = Path.GetDirectoryName(dstName);

            if(!Directory.Exists(destDir))
            {
                Directory.CreateDirectory(destDir);
            }
            files[i] = file;
            dests[i] = dstName;
        }
        if(useJit)
        {
            CompileLuaJit(files,dests);
        }
        else
        {
            CompileLua(files,dests);
        }
        AssetDatabase.Refresh();

        PackDir(fixLuaDIr,"*.bytes",SearchOption.AllDirectories);
        return true;
    }
使用打包方法进行打包
public AssetBundleManifest BuildAllAssetRes()
    {
        if (!Directory.Exists(_targetDir)) Directory.CreateDirectory(_targetDir);
        return BuildPipeline.BuildAssetBundles(_targetDir, BuildAssetBundleOptions.None, _target);
    }
打包调用
static void BuildAllResources(BuildTarget buildTarget)
        {
            Package pack = new Package(buildTarget);
            try { Directory.Delete(pack.targetDir, true); } catch(Exception c) { UnityEngine.Debug.LogError(c.Message); }

            foreach(var item in PackageConfig.instance.packItems)
            {
                if(item.type== PackageItem.PackType.File)
                {
                    pack.PackFile(item.path);
                }else if(item.type==PackageItem.PackType.DirFiles)
                {
                    pack.PackDirFiles(item.path,item.searchPattern,item.searchOption);
                }else if(item.type==PackageItem.PackType.Dir)
                {
                    pack.PackDir(item.path,item.searchPattern,item.searchOption);
                }
            }
            pack.PackLuaDir("lua/", PackageConfig.instance.luaJit);
            AssetBundleManifest manifest = pack.BuildAllAssetRes();


        }