若愚

  • 首页
  • 开发记录
  • 心悟感想
    • 书生意气
    • 随心杂谈
  • 我的简介
    • 吾辈简介
    • 慷概解囊
若愚
独坐残床不思量,一盏昏灯照孤郎
  1. 首页
  2. 开发记录
  3. 正文

实现Addressables打包工具

2021年12月23日 1235点热度 0人点赞 0条评论

背景:

       转眼2021要结束了,我在《赶海王》也只剩下最后一个版本。测试策划们都在忙于提交版本,而我想起了原本想用的addressables打包方式,于是便稍作研究,写了一个类似MotionFramework思路的自动打包工具,只是对关键节点做一些调整就可以完成。开始之前可以先移步学习一下MotionFramework的思路。

https://github.com/gmhevinci/MotionFramework

收集规则(AddressablesCollectorSetting):

需要实现的类包括:

  1. AddressablesCollectorSetting : ScriptableObject,可视化编辑的配置
  2. AddressablesCollectorSettingWindow,可视化编辑的UI
  3. IFilterRule,过滤规则及部分实现,CollectAll,CollectScene等
  4. IPackRule,打包规则,PackExplicit,PackDirectory

实现方式基本保持了MotionFramework中实现并无多大改动:

打包过程拆解:

需要实现的类包括:

  1. TaskPrepare,主要判断配置及打包的前置条件
    public class TaskPrepare : BuildTask
    	{
    		public TaskPrepare(AddressablesBuilder builder):base(builder)
    		{
    			output = new BuildTaskOutput();
    		}
    
    		public override BuildTaskOutput Run()
    		{
    			StartupParameters parameters = builder.StartupParameters;
    
    			// 检测构建平台是否合法
    			if (parameters.BuildTarget == BuildTarget.NoTarget)
    				throw new Exception("请选择目标平台");
    
    			if (parameters.BuildVersion < 0)
    				throw new Exception("请先设置版本号");
    
    			// 检测资源收集配置文件
    			if (AddressablesCollectorSettingData.GetCollecterCount() == 0)
    				throw new Exception("配置的资源收集路径为空!");
    
    			output.IsSuccess = true;
    
    			Debug.Log($"Build Prepare");
    			return output;
    		}
    	}

     

  2. TaskGenerateBuildMap,根据配置文件找到需要打包的资源并给他们设置Group
    /// <summary>
    		/// 获取构建的资源列表
    		/// </summary>
    		private List<AssetInfo> GetBuildAssets()
    		{
    			Dictionary<string, AssetInfo> buildAssets = new Dictionary<string, AssetInfo>();
    			Dictionary<string, string> references = new Dictionary<string, string>();
    
    			// 1. 获取主动收集的资源
    			List<AssetCollectInfo> allCollectAssets = AddressablesCollectorSettingData.GetAllCollectAssets();
    
    			// 2. 对收集的资源进行依赖分析
    			int progressValue = 0;
    			foreach (AssetCollectInfo collectInfo in allCollectAssets)
    			{
    				string mainAssetPath = collectInfo.AssetPath;
    				List<AssetInfo> depends = GetDependencies(collectInfo);
    
    				for (int i = 0; i < depends.Count; i++)
    				{
    					AssetInfo assetInfo = depends[i];
    					if (buildAssets.ContainsKey(assetInfo.AssetPath))
    					{
    						buildAssets[assetInfo.AssetPath].DependCount++;
    						if (assetInfo.GroupName != AddressablesCollectorSettingData.CollectGroupDefault)
    						{
    							buildAssets[assetInfo.AssetPath].RenameGroupName(assetInfo.GroupName);
    						}
    					}
    					else
    					{
    						buildAssets.Add(assetInfo.AssetPath, assetInfo);
    						references.Add(assetInfo.AssetPath, mainAssetPath);
    					}
    
    					// 注意:检测是否为主动收集资源
    					if (assetInfo.AssetPath == mainAssetPath)
    					{
    						buildAssets[mainAssetPath].IsCollectAsset = true;
    					}
    				}
    
    				EditorTools.DisplayProgressBar("依赖文件分析", ++progressValue, allCollectAssets.Count);
    			}
    			EditorTools.ClearProgressBar();
    
    			// 3. 移除零依赖的资源
    			List<AssetInfo> undependentAssets = new List<AssetInfo>();
    			foreach (KeyValuePair<string, AssetInfo> pair in buildAssets)
    			{
    				if (pair.Value.IsCollectAsset)
    					continue;
    				if (pair.Value.DependCount == 0)
    					undependentAssets.Add(pair.Value);
    			}
    			foreach (var assetInfo in undependentAssets)
    			{
    				buildAssets.Remove(assetInfo.AssetPath);
    			}
    
    			// 4. 设置资源标签
    			progressValue = 0;
    			foreach (KeyValuePair<string, AssetInfo> pair in buildAssets)
    			{
    				var assetInfo = pair.Value;
    				// assetInfo.SetBundleLabel(assetInfo.AssetPath);
    				EditorTools.DisplayProgressBar("设置资源标签", ++progressValue, buildAssets.Count);
    			}
    
    			EditorTools.ClearProgressBar();
    
    			// 5. 补充零依赖的资源
    			foreach (var assetInfo in undependentAssets)
    			{
    				var referenceAssetPath = references[assetInfo.AssetPath];
    				var referenceAssetInfo = buildAssets[referenceAssetPath];
    				// assetInfo.SetBundleLabel(referenceAssetInfo.AssetBundleLabel);
    				buildAssets.Add(assetInfo.AssetPath, assetInfo);
    			}
    
    			// 6. 返回结果
    			return buildAssets.Values.ToList();
    		}

     

  3. TaskBuildAdressables,进行打包参数设置,其实最大的区别在这个步骤
    private AddressableAssetGroup GetOrCreateGroup(AddressableAssetSettings settings, string groupName)
    		{
    			AddressableAssetGroup group = settings.FindGroup(groupName);
    			if (group == null)
    			{
    				group = settings.CreateGroup(groupName, false, false, false, null);
    			}
    			else
    			{
    				return group;
    			}
    
    			var bundleSchema = group.GetSchema<BundledAssetGroupSchema>();
    			if (bundleSchema == null)
    			{
    				bundleSchema = group.AddSchema<BundledAssetGroupSchema>();
    				bundleSchema.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kLocalBuildPath);
    				bundleSchema.LoadPath.SetVariableByName(settings, AddressableAssetSettings.kLocalLoadPath);
    
    				bundleSchema.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackSeparately;
    				bundleSchema.Compression = BundledAssetGroupSchema.BundleCompressionMode.LZ4;
    			}
    
    			var updateSchema = group.GetSchema<ContentUpdateGroupSchema>();
    			if (updateSchema == null)
    			{
    				updateSchema = group.AddSchema<ContentUpdateGroupSchema>();
    				updateSchema.StaticContent = true;
    			}
    
    			return group;
    		}
    public override BuildTaskOutput Run()
    		{
    			var settings = AddressablesBuilder.Settings;
    
    			BuildTaskBuildMapOutput buildMapOutput = builder.GetBuildTaskOut<BuildTaskBuildMapOutput>(typeof(TaskGenerateBuildMap));
    			var assets = buildMapOutput.BuildAssets;
    
    			foreach (var asset in assets)
    			{
    				string groupName = asset.GroupName;
    				AddressableAssetGroup group = GetOrCreateGroup(settings, groupName);
    				if (group == null)
    					continue;
    
    				var assetGUID = AssetDatabase.AssetPathToGUID(asset.AssetPath);
    				AddressableAssetEntry entry = settings.CreateOrMoveEntry(assetGUID, group, false, false);
    				string name = asset.AssetPath.RemoveExtension();
    				entry.address = name;
    			}
    
    			AddressableAssetSettings.BuildPlayerContent();
    
    			output.IsSuccess = true;
    
    			return output;
    		}

    注意:分组的规则大致是PackDirectory单独设置一个打包组,其他都放到默认组中,当组名放生冲突的时候,优先PackDirectory组

  4. TaskBuildPackage,没有什么东西,就是打包
  5. TaskCleanAddressables,清空addressables参数设置
    public override BuildTaskOutput Run()
    		{
    			AddressableAssetSettings.CleanPlayerContent(null);
    			BuildCache.PurgeCache(false);
    
    			var setting = AddressablesBuilder.Settings;
    
    			var groups = setting.groups;
    			for (int i = groups.Count - 1; i >= 0; i--)
    			{
    				setting.RemoveGroup(groups[i]);
    			}
    
    			string cachePath = setting.RemoteCatalogLoadPath.GetValue(setting);
    			if (Directory.Exists(cachePath))
    			{
    				Directory.Delete(cachePath, true);
    			}
    
                            EditorUtility.SetDirty(setting);
                            AssetDatabase.SaveAssets();
    
    			output.IsSuccess = true;
    			return output;
    		}

打包入口:

最后找个打包的入口

[MenuItem("Tools/TBuild")]
	public static void TBuild()
	{
		AddressablesBuilder.AddressablesBuilder builder = new AddressablesBuilder.AddressablesBuilder();

		StartupParameters bp = new StartupParameters();
		bp.BuildTarget = BuildTarget.Android;
		bp.BuildVersion = 1;
		bp.BuildPackage = true;

		builder.Run(bp);
	}
标签: 暂无
最后更新:2025年12月14日

admin

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

归档

  • 2022 年 9 月
  • 2022 年 2 月
  • 2021 年 12 月
  • 2021 年 10 月
  • 2021 年 7 月
  • 2021 年 6 月
  • 2021 年 3 月
  • 2019 年 11 月
  • 2019 年 4 月
  • 2018 年 6 月
  • 2018 年 4 月
  • 2018 年 3 月
  • 2017 年 6 月
  • 2017 年 2 月
  • 2016 年 3 月

分类

  • 书生意气
  • 小游戏
  • 开发记录
  • 我的游戏
  • 随心杂谈

COPYRIGHT © 2025 若愚. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

豫ICP备19041692号