前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >unity3d:Assetbundle模拟加载,同步加载,异步加载,依赖包加载,自动标签,AB浏览器,增量打包

unity3d:Assetbundle模拟加载,同步加载,异步加载,依赖包加载,自动标签,AB浏览器,增量打包

作者头像
立羽
发布2023-08-24 15:34:59
发布2023-08-24 15:34:59
55900
代码可运行
举报
文章被收录于专栏:Unity3d程序开发Unity3d程序开发
运行总次数:0
代码可运行

AB自动设置标签

文件夹中每个prefab,单独打包成一个assetbundle,使用于模型,单个UI面板

文件夹内每个文件夹打包成一个assetbundle,适用于图集

所有AB分发器配置数据在Editor/AssetBundle/Database/AssetPackage中,该目录下存在目录的一个映射结构,其中的每个序列化文件对应一个AB分发器

在打包前执行 make tag,通过读上面对应配置,自动设置ab标签与名字

代码语言:javascript
代码运行次数:0
复制
        public AssetBundleChecker(AssetBundleCheckerConfig config)
        {
            this.config = config;
            assetsPath = AssetBundleUtility.PackagePathToAssetsPath(config.PackagePath);
            importer = AssetBundleImporter.GetAtPath(assetsPath);
        }

        public void CheckAssetBundleName()
        {
            if (!importer.IsValid)
            {
                return;
            }

            var checkerFilters = config.CheckerFilters;
            if (checkerFilters == null || checkerFilters.Count == 0)
            {
                importer.assetBundleName = assetsPath;
                string[] bufName = importer.assetBundleName.Split('.');
                MenuAssetBundle.m_abNameStr.AppendFormat("public const string {0} = \"{1}\";", bufName[0], bufName[0]);
                MenuAssetBundle.m_abNameStr.AppendLine();
            }

AB打包

采用增量打包方式,只会打包改动的资源 BuildPipeline.BuildAssetBundles(info.outputDirectory, info.options, info.buildTarget); 调用该函数,unity会自动根据资源的标签进行打包,而且是增量打包,

  1. 对于资源没有变更的bundle包,不会触发重新打包;
  2. 资源没变,即使生成目录下的bundle包被删除了,unity也不会重新打包;
  3. 生成目录下的bundle包对应的manifase被删了,会重新打包;
  4. 可以使用BuildAssetBundleOptions.ForceRebuildAssetBundle参数触发强制重新打包。

打包完毕把md5信息写入

代码语言:javascript
代码运行次数:0
复制
FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
            StreamWriter sw = new StreamWriter(fs);
            for (int i = 0; i < files.Count; i++)
            {
                string file = files[i];
                //if (file.Contains("StreamingAssets")) continue;
                string ext = Path.GetExtension(file);
                if (file.EndsWith(".meta") || file.Contains(".DS_Store")) continue;

                string md5 = NTG.Util.md5file(file);
                string value = file.Replace(m_OutputPath + "/", string.Empty);

                FileInfo fileInfo = new FileInfo(file);
                int size = (int)(fileInfo.Length / 1024) + 1;

                //if (value != "StreamingAssets" && value != "StreamingAssets.manifest")
                sw.WriteLine(value + "|" + md5 + "|" + size);
            }
            sw.Close(); fs.Close();

AB包浏览器

方便查看一个ab包内具体包含哪些

黄色的是代表被多个ab包包含的资源

AB异步加载

编辑器下绕过打包模拟加载

代码语言:javascript
代码运行次数:0
复制
if (SimulateAssetBundleInEditor)
			{
				string[] assetPaths = AssetDatabase.GetAssetPathsFromAssetBundleAndAssetName(assetBundleName, assetName);
				if (assetPaths.Length == 0)
				{
					Debug.LogError("There is no asset with name \"" + assetName + "\" in " + assetBundleName);
					return null;
				}

                // @TODO: Now we only get the main object from the first asset. Should consider type also.
                UnityEngine.Object target = AssetDatabase.LoadMainAssetAtPath(assetPaths[0]);
				operation = new AssetBundleLoadAssetOperationSimulation (target);
			}

异步加载

代码语言:javascript
代码运行次数:0
复制
static public AssetBundleLoadAssetOperation LoadAssetAsync (string assetBundleName, string assetName, System.Type type,string path = "")
		{
			Log(LogType.Info, "Loading " + assetName + " from " + assetBundleName + " bundle");
	
			AssetBundleLoadAssetOperation operation = null;
            {
                assetBundleName = RemapVariantName (assetBundleName);
				LoadAssetBundle (assetBundleName,false,path);
				operation = new AssetBundleLoadAssetOperationFull (assetBundleName, assetName, type);
	
				m_InProgressOperations.Add (operation);
			}
	
			return operation;
		}

加载依赖项:

  1. 加载a生成一个AssetBundleLoadOperation,为异步操作加载
代码语言:javascript
代码运行次数:0
复制
public abstract class AssetBundleLoadOperation : IEnumerator
	{
		public object Current
		{
			get
			{
				return null;
			}
		}
		public bool MoveNext()
		{
			return !IsDone();
		}
		
		public void Reset()
		{
		}
		
		abstract public bool Update ();
		
		abstract public bool IsDone ();
	}
  1. 找到a所有依赖ab包(例如b,c)
代码语言:javascript
代码运行次数:0
复制
string[] dependencies = m_AssetBundleManifest.GetAllDependencies(assetBundleName);
			if (dependencies.Length == 0)
				return;
				
			for (int i=0;i<dependencies.Length;i++)
				dependencies[i] = RemapVariantName (dependencies[i]);
				
			// Record and load all dependencies.
			m_Dependencies.Add(assetBundleName, dependencies);
			for (int i=0;i<dependencies.Length;i++)
				LoadAssetBundleInternal(dependencies[i], false,path);
  1. 把b,c加入到m_DownloadingWWWs中,用www加载
  2. AssetBundleManager中update判断m_DownloadingWWWs每加载完一项,放入到m_LoadedAssetBundles已加载完ab表中
  3. 在AssetBundleManager的Update中遍历m_InProgressOperations中每一项AssetBundleLoadOperation,在a的AssetBundleLoadOperation的update中判断它的依赖b,c是否全部加载完(在m_LoadedAssetBundles中找到值),依赖全加载完,执行加载a的自身ab的请求m_Request = bundle.m_AssetBundle.LoadAssetAsync (m_AssetName, m_Type);
  4. b,c先加载完,a再加载完,AssetBundleLoadOperation中MoveNext返回false,代表执行完毕,可以根据ab包实例化gameobjec之类

同步加载

代码语言:javascript
代码运行次数:0
复制
static private AssetBundle LoadAssetBundleSync(string abname, string abPath = "")
        {

            AssetBundle bundle = null;
            if (!m_LoadedAssetBundles.ContainsKey(abname))
            {
                //byte[] stream = null;
                string uri;
                if (abPath != "")
                {
                    uri = abPath + "/" + abname;
                }
                else
                {
                    uri = AppConst.AbDataPath + "/" + abname;
                }
                //Debug.Log("Loading AssetBundle: " + uri);

                if (!File.Exists(uri))
                {
                    Debug.LogError(String.Format("AssetBundle {0} Not Found", uri));
                    return null;
                }

                //stream = File.ReadAllBytes(uri);

                bundle = AssetBundle.LoadFromFile(uri);
                //stream = null;
                LoadedAssetBundle loBundle = new LoadedAssetBundle(bundle);
          
                m_LoadedAssetBundles.Add(abname, loBundle);

                if (m_Dependencies != null && m_Dependencies.ContainsKey(abname))
                {
                    for (int i = 0; i < m_Dependencies[abname].Length; i++)
                    {
                        LoadAssetBundleSync(m_Dependencies[abname][i]);
                    }
                }
            }
            else
            {
                LoadedAssetBundle loBundle = null;
                m_LoadedAssetBundles.TryGetValue(abname, out loBundle);
                bundle = loBundle.m_AssetBundle;
            }
            return bundle;
        }

关于AssetBundle.LoadFromMemroy内存翻倍问题

LoadFromMemroy即使在PC平台也不如LoadFromFile接口,经测试,PC上LoadFromMemroy接口内存的占用大概会高1/5左右,加载时间比LoadFromFile接口慢1/5左右,而且如loy_liu所说的,LoadFromMemroy接口需要先读取byte[]数组,会导致mono内存的分配,而LoadFromFile不会。 在android平台上,内存的对比将会非常夸张,我这边测试的数据是翻了接近3倍。 所以千万别用LoadFromMemroy接口,LoadFromStream接口没有去测试它的性能和内存,据说和LoadFromFile差不多。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AB自动设置标签
  • AB打包
  • AB包浏览器
  • AB异步加载
    • 编辑器下绕过打包模拟加载
    • 异步加载
    • 同步加载
    • 关于AssetBundle.LoadFromMemroy内存翻倍问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档