【m】框架大更新
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCopyBuildinFiles
|
||||
{
|
||||
/// <summary>
|
||||
/// 拷贝首包资源文件
|
||||
/// </summary>
|
||||
internal void CopyBuildinFilesToStreaming(BuildParametersContext buildParametersContext, PackageManifest manifest)
|
||||
{
|
||||
EBuildinFileCopyOption copyOption = buildParametersContext.Parameters.BuildinFileCopyOption;
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
||||
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
||||
string buildPackageVersion = buildParametersContext.Parameters.PackageVersion;
|
||||
|
||||
// 清空内置文件的目录
|
||||
if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.ClearAndCopyByTags)
|
||||
{
|
||||
EditorTools.ClearFolder(buildinRootDirectory);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildPackageName, buildPackageVersion);
|
||||
string sourcePath = $"{packageOutputDirectory}/{fileName}";
|
||||
string destPath = $"{buildinRootDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单哈希文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildPackageName, buildPackageVersion);
|
||||
string sourcePath = $"{packageOutputDirectory}/{fileName}";
|
||||
string destPath = $"{buildinRootDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单版本文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildPackageName);
|
||||
string sourcePath = $"{packageOutputDirectory}/{fileName}";
|
||||
string destPath = $"{buildinRootDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝文件列表(所有文件)
|
||||
if (copyOption == EBuildinFileCopyOption.ClearAndCopyAll || copyOption == EBuildinFileCopyOption.OnlyCopyAll)
|
||||
{
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
|
||||
string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 拷贝文件列表(带标签的文件)
|
||||
if (copyOption == EBuildinFileCopyOption.ClearAndCopyByTags || copyOption == EBuildinFileCopyOption.OnlyCopyByTags)
|
||||
{
|
||||
string[] tags = buildParametersContext.Parameters.BuildinFileCopyParams.Split(';');
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
if (packageBundle.HasTag(tags) == false)
|
||||
continue;
|
||||
string sourcePath = $"{packageOutputDirectory}/{packageBundle.FileName}";
|
||||
string destPath = $"{buildinRootDirectory}/{packageBundle.FileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新目录
|
||||
AssetDatabase.Refresh();
|
||||
BuildLogger.Log($"Buildin files copy complete: {buildinRootDirectory}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aecf05051992ad14e833529101559071
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCreateCatalog
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成内置资源记录文件
|
||||
/// </summary>
|
||||
internal void CreateCatalogFile(BuildParametersContext buildParametersContext)
|
||||
{
|
||||
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
|
||||
string buildPackageName = buildParametersContext.Parameters.PackageName;
|
||||
var manifestServices = buildParametersContext.Parameters.ManifestRestoreServices;
|
||||
CatalogTools.CreateCatalogFile(manifestServices, buildPackageName, buildinRootDirectory);
|
||||
|
||||
// 刷新目录
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cef6068e037c6904eaed386f5bc3f71a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class ManifestContext : IContextObject
|
||||
{
|
||||
internal PackageManifest Manifest;
|
||||
}
|
||||
|
||||
public abstract class TaskCreateManifest
|
||||
{
|
||||
private readonly Dictionary<string, int> _cachedBundleIndexIDs = new Dictionary<string, int>(10000);
|
||||
private readonly Dictionary<int, HashSet<string>> _cacheBundleTags = new Dictionary<int, HashSet<string>>(10000);
|
||||
|
||||
/// <summary>
|
||||
/// 创建补丁清单文件到输出目录
|
||||
/// </summary>
|
||||
protected void CreateManifestFile(bool processBundleDepends, bool processBundleTags, BuildContext context)
|
||||
{
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
|
||||
// 检测资源包哈希冲突
|
||||
CheckBundleHashConflict(buildMapContext);
|
||||
|
||||
// 创建新补丁清单
|
||||
PackageManifest manifest = new PackageManifest();
|
||||
manifest.FileVersion = ManifestDefine.FileVersion;
|
||||
manifest.EnableAddressable = buildMapContext.Command.EnableAddressable;
|
||||
manifest.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
|
||||
manifest.LocationToLower = buildMapContext.Command.LocationToLower;
|
||||
manifest.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
|
||||
manifest.OutputNameStyle = (int)buildParameters.FileNameStyle;
|
||||
manifest.BuildBundleType = buildParameters.BuildBundleType;
|
||||
manifest.BuildPipeline = buildParameters.BuildPipeline;
|
||||
manifest.PackageName = buildParameters.PackageName;
|
||||
manifest.PackageVersion = buildParameters.PackageVersion;
|
||||
manifest.PackageNote = buildParameters.PackageNote;
|
||||
manifest.AssetList = CreatePackageAssetList(buildMapContext);
|
||||
manifest.BundleList = CreatePackageBundleList(buildMapContext);
|
||||
|
||||
// 1. 处理资源清单的资源对象
|
||||
ProcessPacakgeAsset(manifest);
|
||||
|
||||
// 2. 处理资源包的依赖列表
|
||||
if (processBundleDepends)
|
||||
ProcessBundleDepends(context, manifest);
|
||||
|
||||
// 3. 处理资源包的标签集合
|
||||
if (processBundleTags)
|
||||
ProcessBundleTags(manifest);
|
||||
|
||||
// 4. 处理内置资源包
|
||||
if (processBundleDepends)
|
||||
ProcessBuiltinBundleDependency(context, manifest);
|
||||
|
||||
// 创建资源清单文本文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
ManifestTools.SerializeToJson(filePath, manifest);
|
||||
BuildLogger.Log($"Create package manifest file: {filePath}");
|
||||
}
|
||||
|
||||
// 创建资源清单二进制文件
|
||||
string packageHash;
|
||||
string packagePath;
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetManifestBinaryFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
packagePath = $"{packageOutputDirectory}/{fileName}";
|
||||
ManifestTools.SerializeToBinary(packagePath, manifest, buildParameters.ManifestProcessServices);
|
||||
packageHash = HashUtility.FileCRC32(packagePath);
|
||||
BuildLogger.Log($"Create package manifest file: {packagePath}");
|
||||
}
|
||||
|
||||
// 创建资源清单哈希文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
FileUtility.WriteAllText(filePath, packageHash);
|
||||
BuildLogger.Log($"Create package manifest hash file: {filePath}");
|
||||
}
|
||||
|
||||
// 创建资源清单版本文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
FileUtility.WriteAllText(filePath, buildParameters.PackageVersion);
|
||||
BuildLogger.Log($"Create package manifest version file: {filePath}");
|
||||
}
|
||||
|
||||
// 填充上下文
|
||||
{
|
||||
ManifestContext manifestContext = new ManifestContext();
|
||||
byte[] bytesData = FileUtility.ReadAllBytes(packagePath);
|
||||
manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData, buildParameters.ManifestRestoreServices);
|
||||
context.SetContextObject(manifestContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测资源包哈希冲突
|
||||
/// </summary>
|
||||
private void CheckBundleHashConflict(BuildMapContext buildMapContext)
|
||||
{
|
||||
// 说明:在特殊情况下,例如某些文件加密算法会导致加密后的文件哈希值冲突!
|
||||
// 说明:二进制完全相同的原生文件也会冲突!
|
||||
HashSet<string> guids = new HashSet<string>();
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
if (guids.Contains(bundleInfo.PackageFileHash))
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.BundleHashConflict, $"Bundle hash conflict : {bundleInfo.BundleName}");
|
||||
throw new Exception(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
guids.Add(bundleInfo.PackageFileHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包的依赖集合
|
||||
/// </summary>
|
||||
protected abstract string[] GetBundleDepends(BuildContext context, string bundleName);
|
||||
|
||||
/// <summary>
|
||||
/// 创建资源对象列表
|
||||
/// </summary>
|
||||
private List<PackageAsset> CreatePackageAssetList(BuildMapContext buildMapContext)
|
||||
{
|
||||
List<PackageAsset> result = new List<PackageAsset>(1000);
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
var assetInfos = bundleInfo.GetAllManifestAssetInfos();
|
||||
foreach (var assetInfo in assetInfos)
|
||||
{
|
||||
PackageAsset packageAsset = new PackageAsset();
|
||||
packageAsset.Address = buildMapContext.Command.EnableAddressable ? assetInfo.Address : string.Empty;
|
||||
packageAsset.AssetPath = assetInfo.AssetInfo.AssetPath;
|
||||
packageAsset.AssetGUID = buildMapContext.Command.IncludeAssetGUID ? assetInfo.AssetInfo.AssetGUID : string.Empty;
|
||||
packageAsset.AssetTags = assetInfo.AssetTags.ToArray();
|
||||
packageAsset.TempDataInEditor = assetInfo;
|
||||
result.Add(packageAsset);
|
||||
}
|
||||
}
|
||||
|
||||
// 按照AssetPath排序
|
||||
result.Sort((a, b) => a.AssetPath.CompareTo(b.AssetPath));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建资源包列表
|
||||
/// </summary>
|
||||
private List<PackageBundle> CreatePackageBundleList(BuildMapContext buildMapContext)
|
||||
{
|
||||
List<PackageBundle> result = new List<PackageBundle>(1000);
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
var packageBundle = bundleInfo.CreatePackageBundle();
|
||||
result.Add(packageBundle);
|
||||
}
|
||||
|
||||
// 按照BundleName排序
|
||||
result.Sort((a, b) => a.BundleName.CompareTo(b.BundleName));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理资源清单的资源对象列表
|
||||
/// </summary>
|
||||
private void ProcessPacakgeAsset(PackageManifest manifest)
|
||||
{
|
||||
// 注意:优先缓存资源包索引
|
||||
for (int index = 0; index < manifest.BundleList.Count; index++)
|
||||
{
|
||||
string bundleName = manifest.BundleList[index].BundleName;
|
||||
_cachedBundleIndexIDs.Add(bundleName, index);
|
||||
}
|
||||
|
||||
// 记录资源对象所属的资源包ID
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
var assetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
|
||||
packageAsset.BundleID = GetCachedBundleIndexID(assetInfo.BundleName);
|
||||
}
|
||||
|
||||
// 记录资源对象依赖的资源包ID集合
|
||||
// 注意:依赖关系非引擎构建结果里查询!
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
var mainAssetInfo = packageAsset.TempDataInEditor as BuildAssetInfo;
|
||||
packageAsset.DependBundleIDs = GetAssetDependBundleIDs(mainAssetInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理资源包的依赖集合
|
||||
/// </summary>
|
||||
private void ProcessBundleDepends(BuildContext context, PackageManifest manifest)
|
||||
{
|
||||
// 查询引擎生成的资源包依赖关系,然后记录到清单
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
int mainBundleID = GetCachedBundleIndexID(packageBundle.BundleName);
|
||||
string[] dependNames = GetBundleDepends(context, packageBundle.BundleName);
|
||||
List<int> dependIDs = new List<int>(dependNames.Length);
|
||||
foreach (var dependName in dependNames)
|
||||
{
|
||||
int dependBundleID = GetCachedBundleIndexID(dependName);
|
||||
if (dependBundleID != mainBundleID)
|
||||
dependIDs.Add(dependBundleID);
|
||||
}
|
||||
|
||||
// 排序并填充数据
|
||||
dependIDs.Sort();
|
||||
packageBundle.DependBundleIDs = dependIDs.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理资源包的标签集合
|
||||
/// </summary>
|
||||
private void ProcessBundleTags(PackageManifest manifest)
|
||||
{
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
packageBundle.Tags = Array.Empty<string>();
|
||||
}
|
||||
|
||||
// 将主资源的标签信息传染给其依赖的资源包集合
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
var assetTags = packageAsset.AssetTags;
|
||||
int bundleID = packageAsset.BundleID;
|
||||
CacheBundleTags(bundleID, assetTags);
|
||||
if (packageAsset.DependBundleIDs != null)
|
||||
{
|
||||
foreach (var dependBundleID in packageAsset.DependBundleIDs)
|
||||
{
|
||||
CacheBundleTags(dependBundleID, assetTags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将缓存的资源标签赋值给资源包
|
||||
for (int index = 0; index < manifest.BundleList.Count; index++)
|
||||
{
|
||||
var packageBundle = manifest.BundleList[index];
|
||||
if (_cacheBundleTags.TryGetValue(index, out var value))
|
||||
{
|
||||
packageBundle.Tags = value.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 注意:SBP构建管线会自动剔除一些冗余资源的引用关系,导致游离资源包没有被任何主资源包引用。
|
||||
string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundStrayBundle, $"Found stray bundle ! Bundle ID : {index} Bundle name : {packageBundle.BundleName}");
|
||||
BuildLogger.Warning(warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void CacheBundleTags(int bundleID, string[] assetTags)
|
||||
{
|
||||
if (_cacheBundleTags.ContainsKey(bundleID) == false)
|
||||
_cacheBundleTags.Add(bundleID, new HashSet<string>());
|
||||
|
||||
foreach (var assetTag in assetTags)
|
||||
{
|
||||
if (_cacheBundleTags[bundleID].Contains(assetTag) == false)
|
||||
_cacheBundleTags[bundleID].Add(assetTag);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存的资源包的索引ID
|
||||
/// </summary>
|
||||
private int GetCachedBundleIndexID(string bundleName)
|
||||
{
|
||||
if (_cachedBundleIndexIDs.TryGetValue(bundleName, out int value) == false)
|
||||
{
|
||||
throw new Exception($"Should never get here ! Not found bundle index ID : {bundleName}");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含该资源包的索引ID
|
||||
/// </summary>
|
||||
private bool ContainsCachedBundleIndexID(string bundleName)
|
||||
{
|
||||
return _cachedBundleIndexIDs.ContainsKey(bundleName);
|
||||
}
|
||||
|
||||
#region YOOASSET_LEGACY_DEPENDENCY
|
||||
private void ProcessBuiltinBundleDependency(BuildContext context, PackageManifest manifest)
|
||||
{
|
||||
// 注意:初始化资源清单建立引用关系
|
||||
ManifestTools.InitManifest(manifest);
|
||||
|
||||
// 注意:如果是可编程构建管线,需要补充内置资源包
|
||||
// 注意:该步骤依赖前面的操作!
|
||||
var buildResultContext = context.TryGetContextObject<TaskBuilding_SBP.BuildResultContext>();
|
||||
|
||||
if (buildResultContext != null)
|
||||
{
|
||||
ProcessBuiltinBundleReference(manifest, buildResultContext.BuiltinShadersBundleName);
|
||||
ProcessBuiltinBundleReference(manifest, buildResultContext.MonoScriptsBundleName);
|
||||
|
||||
var buildParametersContext = context.TryGetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
if (buildParameters is ScriptableBuildParameters scriptableBuildParameters)
|
||||
{
|
||||
if (scriptableBuildParameters.TrackSpriteAtlasDependencies)
|
||||
{
|
||||
// 注意:检测是否开启图集模式
|
||||
// 说明:需要记录主资源对象对图集的依赖关系!
|
||||
if (EditorSettings.spritePackerMode != SpritePackerMode.Disabled)
|
||||
{
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
foreach (var spriteAtlasAsset in buildMapContext.SpriteAtlasAssetList)
|
||||
{
|
||||
string spriteAtlasBundleName = spriteAtlasAsset.BundleName;
|
||||
ProcessBuiltinBundleReference(manifest, spriteAtlasBundleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void ProcessBuiltinBundleReference(PackageManifest manifest, string builtinBundleName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(builtinBundleName))
|
||||
return;
|
||||
|
||||
// 查询内置资源包是否存在
|
||||
if (ContainsCachedBundleIndexID(builtinBundleName) == false)
|
||||
return;
|
||||
|
||||
// 获取内置资源包
|
||||
int builtinBundleID = GetCachedBundleIndexID(builtinBundleName);
|
||||
var builtinPackageBundle = manifest.BundleList[builtinBundleID];
|
||||
|
||||
// 更新依赖资源包ID集合
|
||||
HashSet<int> cacheBundleIDs = new HashSet<int>(builtinPackageBundle.ReferenceBundleIDs);
|
||||
HashSet<string> tempTags = new HashSet<string>();
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
if (cacheBundleIDs.Contains(packageAsset.BundleID))
|
||||
{
|
||||
if (packageAsset.DependBundleIDs.Contains(builtinBundleID) == false)
|
||||
{
|
||||
var tempBundleIDs = new List<int>(packageAsset.DependBundleIDs);
|
||||
tempBundleIDs.Add(builtinBundleID);
|
||||
packageAsset.DependBundleIDs = tempBundleIDs.ToArray();
|
||||
}
|
||||
|
||||
foreach (var tag in packageAsset.AssetTags)
|
||||
{
|
||||
if (tempTags.Contains(tag) == false)
|
||||
tempTags.Add(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新内置资源包的标签集合
|
||||
foreach (var tag in builtinPackageBundle.Tags)
|
||||
{
|
||||
if (tempTags.Contains(tag) == false)
|
||||
tempTags.Add(tag);
|
||||
}
|
||||
builtinPackageBundle.Tags = tempTags.ToArray();
|
||||
}
|
||||
private int[] GetAssetDependBundleIDs(BuildAssetInfo mainAssetInfo)
|
||||
{
|
||||
HashSet<int> result = new HashSet<int>();
|
||||
int mainBundleID = GetCachedBundleIndexID(mainAssetInfo.BundleName);
|
||||
foreach (var dependAssetInfo in mainAssetInfo.AllDependAssetInfos)
|
||||
{
|
||||
if (dependAssetInfo.HasBundleName())
|
||||
{
|
||||
int bundleID = GetCachedBundleIndexID(dependAssetInfo.BundleName);
|
||||
if (mainBundleID != bundleID)
|
||||
{
|
||||
if (result.Contains(bundleID) == false)
|
||||
result.Add(bundleID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 排序并返回数据
|
||||
List<int> listResult = new List<int>(result);
|
||||
listResult.Sort();
|
||||
return listResult.ToArray();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ee2c2f00a1d67d45adee1d5200870cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,235 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskCreateReport
|
||||
{
|
||||
protected void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext, ManifestContext manifestContext)
|
||||
{
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
PackageManifest manifest = manifestContext.Manifest;
|
||||
BuildReport buildReport = new BuildReport();
|
||||
|
||||
// 概述信息
|
||||
{
|
||||
buildReport.Summary.YooVersion = EditorTools.GetPackageManagerYooVersion();
|
||||
buildReport.Summary.UnityVersion = UnityEngine.Application.unityVersion;
|
||||
buildReport.Summary.BuildDate = DateTime.Now.ToString();
|
||||
buildReport.Summary.BuildSeconds = BuildRunner.TotalSeconds;
|
||||
buildReport.Summary.BuildTarget = buildParameters.BuildTarget;
|
||||
buildReport.Summary.BuildPipeline = buildParameters.BuildPipeline;
|
||||
buildReport.Summary.BuildBundleType = buildParameters.BuildBundleType;
|
||||
buildReport.Summary.BuildPackageName = buildParameters.PackageName;
|
||||
buildReport.Summary.BuildPackageVersion = buildParameters.PackageVersion;
|
||||
buildReport.Summary.BuildPackageNote = buildParameters.PackageNote;
|
||||
|
||||
// 收集器配置
|
||||
buildReport.Summary.UniqueBundleName = buildMapContext.Command.UniqueBundleName;
|
||||
buildReport.Summary.EnableAddressable = buildMapContext.Command.EnableAddressable;
|
||||
buildReport.Summary.SupportExtensionless = buildMapContext.Command.SupportExtensionless;
|
||||
buildReport.Summary.LocationToLower = buildMapContext.Command.LocationToLower;
|
||||
buildReport.Summary.IncludeAssetGUID = buildMapContext.Command.IncludeAssetGUID;
|
||||
buildReport.Summary.AutoCollectShaders = buildMapContext.Command.AutoCollectShaders;
|
||||
buildReport.Summary.IgnoreRuleName = buildMapContext.Command.IgnoreRule.GetType().FullName;
|
||||
|
||||
// 构建参数
|
||||
buildReport.Summary.ClearBuildCacheFiles = buildParameters.ClearBuildCacheFiles;
|
||||
buildReport.Summary.UseAssetDependencyDB = buildParameters.UseAssetDependencyDB;
|
||||
buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;
|
||||
buildReport.Summary.SingleReferencedPackAlone = buildParameters.SingleReferencedPackAlone;
|
||||
buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
|
||||
buildReport.Summary.EncryptionServicesClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName;
|
||||
buildReport.Summary.ManifestProcessServicesClassName = buildParameters.ManifestProcessServices == null ? "null" : buildParameters.ManifestProcessServices.GetType().FullName;
|
||||
buildReport.Summary.ManifestRestoreServicesClassName = buildParameters.ManifestRestoreServices == null ? "null" : buildParameters.ManifestRestoreServices.GetType().FullName;
|
||||
|
||||
if (buildParameters is BuiltinBuildParameters)
|
||||
{
|
||||
var builtinBuildParameters = buildParameters as BuiltinBuildParameters;
|
||||
buildReport.Summary.CompressOption = builtinBuildParameters.CompressOption;
|
||||
buildReport.Summary.DisableWriteTypeTree = builtinBuildParameters.DisableWriteTypeTree;
|
||||
buildReport.Summary.IgnoreTypeTreeChanges = builtinBuildParameters.IgnoreTypeTreeChanges;
|
||||
}
|
||||
else if (buildParameters is ScriptableBuildParameters)
|
||||
{
|
||||
var scriptableBuildParameters = buildParameters as ScriptableBuildParameters;
|
||||
buildReport.Summary.CompressOption = scriptableBuildParameters.CompressOption;
|
||||
buildReport.Summary.DisableWriteTypeTree = scriptableBuildParameters.DisableWriteTypeTree;
|
||||
buildReport.Summary.IgnoreTypeTreeChanges = scriptableBuildParameters.IgnoreTypeTreeChanges;
|
||||
buildReport.Summary.WriteLinkXML = scriptableBuildParameters.WriteLinkXML;
|
||||
buildReport.Summary.CacheServerHost = scriptableBuildParameters.CacheServerHost;
|
||||
buildReport.Summary.CacheServerPort = scriptableBuildParameters.CacheServerPort;
|
||||
buildReport.Summary.BuiltinShadersBundleName = scriptableBuildParameters.BuiltinShadersBundleName;
|
||||
buildReport.Summary.MonoScriptsBundleName = scriptableBuildParameters.MonoScriptsBundleName;
|
||||
}
|
||||
|
||||
// 构建结果
|
||||
buildReport.Summary.AssetFileTotalCount = buildMapContext.AssetFileCount;
|
||||
buildReport.Summary.MainAssetTotalCount = GetMainAssetCount(manifest);
|
||||
buildReport.Summary.AllBundleTotalCount = GetAllBundleCount(manifest);
|
||||
buildReport.Summary.AllBundleTotalSize = GetAllBundleSize(manifest);
|
||||
buildReport.Summary.EncryptedBundleTotalCount = GetEncryptedBundleCount(manifest);
|
||||
buildReport.Summary.EncryptedBundleTotalSize = GetEncryptedBundleSize(manifest);
|
||||
}
|
||||
|
||||
// 资源对象列表
|
||||
buildReport.AssetInfos = new List<ReportAssetInfo>(manifest.AssetList.Count);
|
||||
foreach (var packageAsset in manifest.AssetList)
|
||||
{
|
||||
var mainBundle = manifest.BundleList[packageAsset.BundleID];
|
||||
ReportAssetInfo reportAssetInfo = new ReportAssetInfo();
|
||||
reportAssetInfo.Address = packageAsset.Address;
|
||||
reportAssetInfo.AssetPath = packageAsset.AssetPath;
|
||||
reportAssetInfo.AssetTags = packageAsset.AssetTags;
|
||||
reportAssetInfo.AssetGUID = AssetDatabase.AssetPathToGUID(packageAsset.AssetPath);
|
||||
reportAssetInfo.MainBundleName = mainBundle.BundleName;
|
||||
reportAssetInfo.MainBundleSize = mainBundle.FileSize;
|
||||
reportAssetInfo.DependAssets = GetAssetDependAssets(buildMapContext, mainBundle.BundleName, packageAsset.AssetPath);
|
||||
reportAssetInfo.DependBundles = GetAssetDependBundles(manifest, packageAsset);
|
||||
buildReport.AssetInfos.Add(reportAssetInfo);
|
||||
}
|
||||
|
||||
// 资源包列表
|
||||
buildReport.BundleInfos = new List<ReportBundleInfo>(manifest.BundleList.Count);
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
ReportBundleInfo reportBundleInfo = new ReportBundleInfo();
|
||||
reportBundleInfo.BundleName = packageBundle.BundleName;
|
||||
reportBundleInfo.FileName = packageBundle.FileName;
|
||||
reportBundleInfo.FileHash = packageBundle.FileHash;
|
||||
reportBundleInfo.FileCRC = packageBundle.FileCRC;
|
||||
reportBundleInfo.FileSize = packageBundle.FileSize;
|
||||
reportBundleInfo.Encrypted = packageBundle.Encrypted;
|
||||
reportBundleInfo.Tags = packageBundle.Tags;
|
||||
reportBundleInfo.DependBundles = GetBundleDependBundles(manifest, packageBundle);
|
||||
reportBundleInfo.ReferenceBundles = GetBundleReferenceBundles(manifest, packageBundle);
|
||||
reportBundleInfo.BundleContents = GetBundleContents(buildMapContext, packageBundle.BundleName);
|
||||
buildReport.BundleInfos.Add(reportBundleInfo);
|
||||
}
|
||||
|
||||
// 其它资源列表
|
||||
buildReport.IndependAssets = new List<ReportIndependAsset>(buildMapContext.IndependAssets);
|
||||
|
||||
// 序列化文件
|
||||
string fileName = YooAssetSettingsData.GetBuildReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
BuildReport.Serialize(filePath, buildReport);
|
||||
BuildLogger.Log($"Create build report file: {filePath}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源对象依赖的其它所有资源
|
||||
/// </summary>
|
||||
private List<AssetInfo> GetAssetDependAssets(BuildMapContext buildMapContext, string bundleName, string assetPath)
|
||||
{
|
||||
List<AssetInfo> result = new List<AssetInfo>();
|
||||
var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
|
||||
var assetInfo = bundleInfo.GetPackAssetInfo(assetPath);
|
||||
foreach (var dependAssetInfo in assetInfo.AllDependAssetInfos)
|
||||
{
|
||||
result.Add(dependAssetInfo.AssetInfo);
|
||||
}
|
||||
result.Sort();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源对象依赖的资源包集合
|
||||
/// </summary>
|
||||
private List<string> GetAssetDependBundles(PackageManifest manifest, PackageAsset packageAsset)
|
||||
{
|
||||
List<string> dependBundles = new List<string>(packageAsset.DependBundleIDs.Length);
|
||||
foreach (int index in packageAsset.DependBundleIDs)
|
||||
{
|
||||
string dependBundleName = manifest.BundleList[index].BundleName;
|
||||
dependBundles.Add(dependBundleName);
|
||||
}
|
||||
dependBundles.Sort();
|
||||
return dependBundles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包依赖的资源包集合
|
||||
/// </summary>
|
||||
private List<string> GetBundleDependBundles(PackageManifest manifest, PackageBundle packageBundle)
|
||||
{
|
||||
List<string> dependBundles = new List<string>(packageBundle.DependBundleIDs.Length);
|
||||
foreach (int index in packageBundle.DependBundleIDs)
|
||||
{
|
||||
string dependBundleName = manifest.BundleList[index].BundleName;
|
||||
dependBundles.Add(dependBundleName);
|
||||
}
|
||||
dependBundles.Sort();
|
||||
return dependBundles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取引用该资源包的资源包集合
|
||||
/// </summary>
|
||||
private List<string> GetBundleReferenceBundles(PackageManifest manifest, PackageBundle packageBundle)
|
||||
{
|
||||
List<string> referenceBundles = new List<string>(packageBundle.ReferenceBundleIDs.Count);
|
||||
foreach (int index in packageBundle.ReferenceBundleIDs)
|
||||
{
|
||||
string dependBundleName = manifest.BundleList[index].BundleName;
|
||||
referenceBundles.Add(dependBundleName);
|
||||
}
|
||||
referenceBundles.Sort();
|
||||
return referenceBundles;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包内部所有资产
|
||||
/// </summary>
|
||||
private List<AssetInfo> GetBundleContents(BuildMapContext buildMapContext, string bundleName)
|
||||
{
|
||||
var bundleInfo = buildMapContext.GetBundleInfo(bundleName);
|
||||
List<AssetInfo> result = bundleInfo.GetBundleContents();
|
||||
result.Sort();
|
||||
return result;
|
||||
}
|
||||
|
||||
private int GetMainAssetCount(PackageManifest manifest)
|
||||
{
|
||||
return manifest.AssetList.Count;
|
||||
}
|
||||
private int GetAllBundleCount(PackageManifest manifest)
|
||||
{
|
||||
return manifest.BundleList.Count;
|
||||
}
|
||||
private long GetAllBundleSize(PackageManifest manifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
fileBytes += packageBundle.FileSize;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
private int GetEncryptedBundleCount(PackageManifest manifest)
|
||||
{
|
||||
int fileCount = 0;
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
if (packageBundle.Encrypted)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
}
|
||||
private long GetEncryptedBundleSize(PackageManifest manifest)
|
||||
{
|
||||
long fileBytes = 0;
|
||||
foreach (var packageBundle in manifest.BundleList)
|
||||
{
|
||||
if (packageBundle.Encrypted)
|
||||
fileBytes += packageBundle.FileSize;
|
||||
}
|
||||
return fileBytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 869f8e34d5e3221428dc9016adf1d2b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// 加密文件
|
||||
/// </summary>
|
||||
public void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
{
|
||||
var encryptionServices = buildParametersContext.Parameters.EncryptionServices;
|
||||
if (encryptionServices == null)
|
||||
return;
|
||||
|
||||
if (encryptionServices.GetType() == typeof(EncryptionNone))
|
||||
return;
|
||||
|
||||
int progressValue = 0;
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
EncryptFileInfo fileInfo = new EncryptFileInfo();
|
||||
fileInfo.BundleName = bundleInfo.BundleName;
|
||||
fileInfo.FileLoadPath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
var encryptResult = encryptionServices.Encrypt(fileInfo);
|
||||
if (encryptResult.Encrypted)
|
||||
{
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt";
|
||||
FileUtility.WriteAllBytes(filePath, encryptResult.EncryptedData);
|
||||
bundleInfo.EncryptedFilePath = filePath;
|
||||
bundleInfo.Encrypted = true;
|
||||
BuildLogger.Log($"Bundle file encryption complete: {filePath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
bundleInfo.Encrypted = false;
|
||||
}
|
||||
|
||||
// 进度条
|
||||
EditorTools.DisplayProgressBar("Encrypting bundle", ++progressValue, buildMapContext.Collection.Count);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f269175a60e227428b7029f09e2578e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class TaskGetBuildMap
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成资源构建上下文
|
||||
/// </summary>
|
||||
public BuildMapContext CreateBuildMap(bool simulateBuild, BuildParameters buildParameters)
|
||||
{
|
||||
BuildMapContext context = new BuildMapContext();
|
||||
var packageName = buildParameters.PackageName;
|
||||
|
||||
Dictionary<string, BuildAssetInfo> allBuildAssetInfos = new Dictionary<string, BuildAssetInfo>(1000);
|
||||
|
||||
// 1. 获取所有收集器收集的资源
|
||||
bool useAssetDependencyDB = buildParameters.UseAssetDependencyDB;
|
||||
var collectResult = AssetBundleCollectorSettingData.Setting.BeginCollect(packageName, simulateBuild, useAssetDependencyDB);
|
||||
List<CollectAssetInfo> allCollectAssets = collectResult.CollectAssets;
|
||||
|
||||
// 2. 剔除未被引用的依赖项资源
|
||||
RemoveZeroReferenceAssets(context, allCollectAssets);
|
||||
|
||||
// 3. 录入所有收集器主动收集的资源
|
||||
foreach (var collectAssetInfo in allCollectAssets)
|
||||
{
|
||||
if (allBuildAssetInfos.ContainsKey(collectAssetInfo.AssetInfo.AssetPath))
|
||||
{
|
||||
throw new Exception($"Should never get here !");
|
||||
}
|
||||
|
||||
if (collectAssetInfo.CollectorType != ECollectorType.MainAssetCollector)
|
||||
{
|
||||
if (collectAssetInfo.AssetTags.Count > 0)
|
||||
{
|
||||
collectAssetInfo.AssetTags.Clear();
|
||||
string warning = BuildLogger.GetErrorMessage(ErrorCode.RemoveInvalidTags, $"Remove asset tags that don't work, see the asset collector type : {collectAssetInfo.AssetInfo.AssetPath}");
|
||||
BuildLogger.Warning(warning);
|
||||
}
|
||||
}
|
||||
|
||||
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.CollectorType, collectAssetInfo.BundleName, collectAssetInfo.Address, collectAssetInfo.AssetInfo);
|
||||
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
|
||||
allBuildAssetInfos.Add(collectAssetInfo.AssetInfo.AssetPath, buildAssetInfo);
|
||||
}
|
||||
|
||||
// 4. 录入所有收集资源依赖的其它资源
|
||||
foreach (var collectAssetInfo in allCollectAssets)
|
||||
{
|
||||
string bundleName = collectAssetInfo.BundleName;
|
||||
foreach (var dependAsset in collectAssetInfo.DependAssets)
|
||||
{
|
||||
if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out var value))
|
||||
{
|
||||
value.AddReferenceBundleName(bundleName);
|
||||
}
|
||||
else
|
||||
{
|
||||
var buildAssetInfo = new BuildAssetInfo(dependAsset);
|
||||
buildAssetInfo.AddReferenceBundleName(bundleName);
|
||||
allBuildAssetInfos.Add(dependAsset.AssetPath, buildAssetInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 填充所有收集资源的依赖列表
|
||||
foreach (var collectAssetInfo in allCollectAssets)
|
||||
{
|
||||
var dependAssetInfos = new List<BuildAssetInfo>(collectAssetInfo.DependAssets.Count);
|
||||
foreach (var dependAsset in collectAssetInfo.DependAssets)
|
||||
{
|
||||
if (allBuildAssetInfos.TryGetValue(dependAsset.AssetPath, out BuildAssetInfo value))
|
||||
dependAssetInfos.Add(value);
|
||||
else
|
||||
throw new Exception("Should never get here !");
|
||||
}
|
||||
allBuildAssetInfos[collectAssetInfo.AssetInfo.AssetPath].SetDependAssetInfos(dependAssetInfos);
|
||||
}
|
||||
|
||||
// 6. 自动收集所有依赖的着色器
|
||||
if (collectResult.Command.AutoCollectShaders)
|
||||
{
|
||||
// 获取着色器打包规则结果
|
||||
PackRuleResult shaderPackRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
|
||||
string shaderBundleName = shaderPackRuleResult.GetBundleName(collectResult.Command.PackageName, collectResult.Command.UniqueBundleName);
|
||||
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
|
||||
{
|
||||
if (buildAssetInfo.CollectorType == ECollectorType.None)
|
||||
{
|
||||
if (buildAssetInfo.AssetInfo.IsShaderAsset())
|
||||
{
|
||||
buildAssetInfo.SetBundleName(shaderBundleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 计算共享资源的包名
|
||||
if (buildParameters.EnableSharePackRule)
|
||||
{
|
||||
PreProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
|
||||
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
|
||||
{
|
||||
if (buildAssetInfo.HasBundleName() == false)
|
||||
{
|
||||
ProcessingPackShareBundle(buildParameters, collectResult.Command, buildAssetInfo);
|
||||
}
|
||||
}
|
||||
PostProcessPackShareBundle(buildParameters, collectResult.Command, allBuildAssetInfos);
|
||||
}
|
||||
|
||||
// 8. 记录关键信息
|
||||
context.AssetFileCount = allBuildAssetInfos.Count;
|
||||
context.Command = collectResult.Command;
|
||||
|
||||
// 9. 移除不参与构建的资源
|
||||
List<BuildAssetInfo> removeBuildList = new List<BuildAssetInfo>();
|
||||
foreach (var buildAssetInfo in allBuildAssetInfos.Values)
|
||||
{
|
||||
if (buildAssetInfo.HasBundleName() == false)
|
||||
removeBuildList.Add(buildAssetInfo);
|
||||
}
|
||||
foreach (var removeValue in removeBuildList)
|
||||
{
|
||||
allBuildAssetInfos.Remove(removeValue.AssetInfo.AssetPath);
|
||||
}
|
||||
|
||||
// 10. 构建资源列表
|
||||
var allPackAssets = allBuildAssetInfos.Values.ToList();
|
||||
if (allPackAssets.Count == 0)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.PackAssetListIsEmpty, "The pack asset info is empty !");
|
||||
throw new Exception(message);
|
||||
}
|
||||
foreach (var assetInfo in allPackAssets)
|
||||
{
|
||||
context.PackAsset(assetInfo);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
private void RemoveZeroReferenceAssets(BuildMapContext context, List<CollectAssetInfo> allCollectAssets)
|
||||
{
|
||||
// 1. 检测依赖资源收集器是否存在
|
||||
if (allCollectAssets.Exists(x => x.CollectorType == ECollectorType.DependAssetCollector) == false)
|
||||
return;
|
||||
|
||||
// 2. 获取所有主资源的依赖资源集合
|
||||
HashSet<string> allDependAsset = new HashSet<string>();
|
||||
foreach (var collectAsset in allCollectAssets)
|
||||
{
|
||||
var collectorType = collectAsset.CollectorType;
|
||||
if (collectorType == ECollectorType.MainAssetCollector || collectorType == ECollectorType.StaticAssetCollector)
|
||||
{
|
||||
foreach (var dependAsset in collectAsset.DependAssets)
|
||||
{
|
||||
if (allDependAsset.Contains(dependAsset.AssetPath) == false)
|
||||
allDependAsset.Add(dependAsset.AssetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 找出所有零引用的依赖资源集合
|
||||
List<CollectAssetInfo> removeList = new List<CollectAssetInfo>();
|
||||
foreach (var collectAssetInfo in allCollectAssets)
|
||||
{
|
||||
var collectorType = collectAssetInfo.CollectorType;
|
||||
if (collectorType == ECollectorType.DependAssetCollector)
|
||||
{
|
||||
if (allDependAsset.Contains(collectAssetInfo.AssetInfo.AssetPath) == false)
|
||||
removeList.Add(collectAssetInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 移除所有零引用的依赖资源
|
||||
foreach (var removeValue in removeList)
|
||||
{
|
||||
string warning = BuildLogger.GetErrorMessage(ErrorCode.FoundUndependedAsset, $"Found undepended asset and remove it : {removeValue.AssetInfo.AssetPath}");
|
||||
BuildLogger.Warning(warning);
|
||||
|
||||
var independAsset = new ReportIndependAsset();
|
||||
independAsset.AssetPath = removeValue.AssetInfo.AssetPath;
|
||||
independAsset.AssetGUID = removeValue.AssetInfo.AssetGUID;
|
||||
independAsset.AssetType = removeValue.AssetInfo.AssetType.ToString();
|
||||
independAsset.FileSize = FileUtility.GetFileSize(removeValue.AssetInfo.AssetPath);
|
||||
context.IndependAssets.Add(independAsset);
|
||||
|
||||
allCollectAssets.Remove(removeValue);
|
||||
}
|
||||
}
|
||||
|
||||
#region 共享资源打包规则
|
||||
/// <summary>
|
||||
/// 共享资源打包前置处理
|
||||
/// </summary>
|
||||
protected virtual void PreProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 共享资源打包机制
|
||||
/// </summary>
|
||||
protected virtual void ProcessingPackShareBundle(BuildParameters buildParameters, CollectCommand command, BuildAssetInfo buildAssetInfo)
|
||||
{
|
||||
PackRuleResult packRuleResult = GetShareBundleName(buildAssetInfo);
|
||||
if (packRuleResult.IsValid() == false)
|
||||
return;
|
||||
|
||||
// 处理单个引用的共享资源
|
||||
if (buildAssetInfo.GetReferenceBundleCount() <= 1)
|
||||
{
|
||||
if (buildParameters.SingleReferencedPackAlone == false)
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置共享资源包名
|
||||
string shareBundleName = packRuleResult.GetShareBundleName(command.PackageName, command.UniqueBundleName);
|
||||
buildAssetInfo.SetBundleName(shareBundleName);
|
||||
}
|
||||
private PackRuleResult GetShareBundleName(BuildAssetInfo buildAssetInfo)
|
||||
{
|
||||
string bundleName = Path.GetDirectoryName(buildAssetInfo.AssetInfo.AssetPath);
|
||||
PackRuleResult result = new PackRuleResult(bundleName, DefaultPackRule.AssetBundleFileExtension);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 共享资源打包后置处理
|
||||
/// </summary>
|
||||
protected virtual void PostProcessPackShareBundle(BuildParameters buildParameters, CollectCommand command, Dictionary<string, BuildAssetInfo> allBuildAssetInfos)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0ea8b7c5a6b8ee4dabc4ccfd1516fc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public abstract class TaskUpdateBundleInfo
|
||||
{
|
||||
public void UpdateBundleInfo(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
int outputNameStyle = (int)buildParametersContext.Parameters.FileNameStyle;
|
||||
|
||||
// 1.检测文件名长度
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
// NOTE:检测文件名长度不要超过260字符。
|
||||
string fileName = bundleInfo.BundleName;
|
||||
if (fileName.Length >= 260)
|
||||
{
|
||||
string message = BuildLogger.GetErrorMessage(ErrorCode.CharactersOverTheLimit, $"Bundle file name character count exceeds limit : {fileName}");
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
// 2.更新构建输出的文件路径
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
bundleInfo.BuildOutputFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
if (bundleInfo.Encrypted)
|
||||
bundleInfo.PackageSourceFilePath = bundleInfo.EncryptedFilePath;
|
||||
else
|
||||
bundleInfo.PackageSourceFilePath = bundleInfo.BuildOutputFilePath;
|
||||
}
|
||||
|
||||
// 3.更新文件其它信息
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
bundleInfo.PackageUnityHash = GetUnityHash(bundleInfo, context);
|
||||
bundleInfo.PackageUnityCRC = GetUnityCRC(bundleInfo, context);
|
||||
bundleInfo.PackageFileHash = GetBundleFileHash(bundleInfo, buildParametersContext);
|
||||
bundleInfo.PackageFileCRC = GetBundleFileCRC(bundleInfo, buildParametersContext);
|
||||
bundleInfo.PackageFileSize = GetBundleFileSize(bundleInfo, buildParametersContext);
|
||||
}
|
||||
|
||||
// 4.更新补丁包输出的文件路径
|
||||
foreach (var bundleInfo in buildMapContext.Collection)
|
||||
{
|
||||
string bundleName = bundleInfo.BundleName;
|
||||
string fileHash = bundleInfo.PackageFileHash;
|
||||
string fileExtension = ManifestTools.GetRemoteBundleFileExtension(bundleName);
|
||||
string fileName = ManifestTools.GetRemoteBundleFileName(outputNameStyle, bundleName, fileExtension, fileHash);
|
||||
bundleInfo.PackageDestFilePath = $"{packageOutputDirectory}/{fileName}";
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract string GetUnityHash(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract uint GetUnityCRC(BuildBundleInfo bundleInfo, BuildContext context);
|
||||
protected abstract string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
protected abstract uint GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
protected abstract long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dda2f1ef3b6c4e48a398217335b55f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user