Unity simple packaging script

packaging script

This packaging script is suitable for demo. The script is placed in the Editor directory.

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

public class BuildAB
{
    
    
    [MenuItem("Tools/递归遍历文件夹下的资源并打包")]
    public static void BuildDirectory()
    {
    
    
        //需要打包的文件夹路径
        string path = Application.dataPath + "/Res";
        List<string> list = new List<string>();
        GetFilePath(path, ref list);

        List<AssetBundleBuild> mult = new List<AssetBundleBuild>();
        for (int i = 0; i < list.Count; i++)
        {
    
    
            string assetName = list[i].Replace(Application.dataPath, "Assets").Replace("\\", "/");
            string bundleName = Path.GetFileNameWithoutExtension(assetName);

            AssetBundleBuild ab = new AssetBundleBuild();
            ab.assetBundleName = bundleName;
            //assetNames记录bundle中所有资源的相对路径
            ab.assetNames = new string[] {
    
     assetName };
            mult.Add(ab);

            Debug.Log($"{
      
      assetName} {
      
      bundleName}");
        }

        string targetPath = Application.streamingAssetsPath;
        if (Directory.Exists(targetPath))
            Directory.Delete(targetPath, true);
        Directory.CreateDirectory(targetPath);

        BuildPipeline.BuildAssetBundles(targetPath, mult.ToArray(),
            BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);

        AssetDatabase.Refresh();
    }

    [MenuItem("Tools/遍历文件夹下的资源,处理依赖并打包")]
    public static void BuildDirectoryDependence()
    {
    
    
        string path = Application.dataPath + "/Res";
        List<string> list = new List<string>();
        GetFilePath(path, ref list);

        //key 资源路径,value 引用计数
        Dictionary<string, int> abDict = new Dictionary<string, int>();
        for (int i = 0; i < list.Count; i++)
        {
    
    
            string assetName = list[i].Replace(Application.dataPath, "Assets").Replace("\\", "/");

            //获取依赖资源,返回相对路径
            string[] dependences = AssetDatabase.GetDependencies(assetName);
            for(int j = 0; j < dependences.Length; ++j)
            {
    
    
                if (dependences[j].EndsWith(".cs"))
                {
    
    
                    continue;
                }

                Debug.Log($"{
      
      assetName} 依赖 {
      
      j} => {
      
      dependences[j]}");
                if (abDict.ContainsKey(dependences[j]))
                {
    
    
                    abDict[dependences[j]]++;
                }
                else
                {
    
    
                    abDict.Add(dependences[j], 1);
                }
            }
        }

        var enumerator = abDict.GetEnumerator();
        List<AssetBundleBuild> mult = new List<AssetBundleBuild>();
        while (enumerator.MoveNext())
        {
    
    
            string fileName = enumerator.Current.Key;
            int refCount = enumerator.Current.Value;

            string bundleName = Path.GetFileNameWithoutExtension(fileName);
            if(refCount > 1)
            {
    
    
                //引用计数大于1的为公共资源,单独打包
                bundleName = "common/" + bundleName;
            }

            AssetBundleBuild ab = new AssetBundleBuild();
            ab.assetBundleName = bundleName;
            //assetNames记录bundle中所有资源的相对路径
            ab.assetNames = new string[] {
    
     fileName };
            mult.Add(ab);
        }

        string targetPath = Application.streamingAssetsPath;
        if (Directory.Exists(targetPath))
            Directory.Delete(targetPath, true);
        Directory.CreateDirectory(targetPath);

        BuildPipeline.BuildAssetBundles(targetPath, mult.ToArray(),
            BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);

        AssetDatabase.Refresh();
    }

    /// <summary>
    /// 递归获取所有文件路径
    /// </summary>
    public static void GetFilePath(string path, ref List<string> list)
    {
    
    
        string[] files = Directory.GetFiles(path);
        for (int i = 0; i < files.Length; i++)
        {
    
    
            if (files[i].EndsWith(".cs") || files[i].EndsWith(".meta"))
            {
    
    
                continue;
            }

            list.Add(files[i]);
        }

        string[] dirs = Directory.GetDirectories(path);
        for(int i = 0; i < dirs.Length; i++)
        {
    
    
            GetFilePath(dirs[i], ref list);
        }
    }
}

Insert image description here
The previous option will not handle dependencies, and public resources will be put into different bundles.
The following options will handle dependent resources. Those with a reference count greater than 1 are considered public resources. Packaged separately into common folder

Load script

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

public class LoadAB : MonoBehaviour
{
    
    
    private AssetBundleManifest _manifest;
    private List<string> _abList = new List<string>();
    private Dictionary<string, GameObject> _assetDict = new Dictionary<string, GameObject>();

    void Start()
    {
    
    
        LoadManifest();
        LoadGameObject("cube");
    }

    void LoadManifest()
    {
    
    
        AssetBundle assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/StreamingAssets");
        _manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }

    private void LoadGameObject(string abName)
    {
    
    
        if (string.IsNullOrEmpty(abName))
            return;

        abName = abName.ToLower();

		//先加载依赖资源
        string[] dependens = _manifest.GetAllDependencies(abName);
        for (int i = 0; i < dependens.Length; ++i)
        {
    
    
            if (!_abList.Contains(dependens[i]))
            {
    
    
                AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + dependens[i]);
                _abList.Add(dependens[i]);
            }
        }

        if (!_abList.Contains(abName))
        {
    
    
            AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + abName);
            _abList.Add(abName);
            _assetDict.Add(abName, ab.LoadAsset<GameObject>(abName));
        }

        if (_assetDict.ContainsKey(abName))
        {
    
    
            GameObject.Instantiate(_assetDict[abName]);
        }
    }
}

reference

untiy AssetBundle dependency tree

Guess you like

Origin blog.csdn.net/sinat_34014668/article/details/134657934