Compare commits

...

27 Commits

Author SHA1 Message Date
黑黑面麻的快乐生活
3ddfed4bf1 Merge 1c4aba6db5 into e57466e9e2 2025-06-25 19:06:49 +08:00
何冠峰
e57466e9e2 style : file system code 2025-06-25 18:12:37 +08:00
何冠峰
6f7fca7b34 perf : main thread sleep one 2025-06-25 18:10:50 +08:00
何冠峰
756331fe0b style : file system code 2025-06-25 18:04:53 +08:00
何冠峰
5139e2f3a7 update extension sample 2025-06-23 18:57:48 +08:00
hhmmLife
1c4aba6db5 fix: 只有递归收集依赖时,依赖列表中才默认包含主资源 2025-06-23 00:56:50 +08:00
何冠峰
44faa0c5e6 fix #572
修复了资源收集页面指定收集的预制体名称变动的问题。
2025-06-20 17:55:51 +08:00
何冠峰
72c97341b1 fix #579 2025-06-20 14:03:12 +08:00
何冠峰
9acc240b5a update extension sample 2025-06-20 11:36:56 +08:00
何冠峰
ed89e73d26 fix #576
资源清单加密和解密
2025-06-20 11:36:29 +08:00
何冠峰
9e33df0375 style :services code 2025-06-20 11:29:22 +08:00
何冠峰
6c98f9a09d update resource manager
新增初始化参数:WebGLForceSyncLoadAsset
2025-06-18 11:12:42 +08:00
何冠峰
9ed85afb29 Update CHANGELOG.md 2025-06-17 19:26:39 +08:00
何冠峰
560a395173 Update CHANGELOG.md 2025-06-17 19:23:57 +08:00
何冠峰
8bce963588 Update package.json 2025-06-17 19:23:32 +08:00
何冠峰
f8a3fe47e5 add mini game sample
修复程序集不正确的问题
2025-06-17 18:29:17 +08:00
何冠峰
48356a4f9e fix #573 2025-06-17 18:20:28 +08:00
何冠峰
d2a28bd801 fix #562 2025-06-17 17:07:02 +08:00
何冠峰
3949abb53f fix #566
重构了资源构建页面,方便扩展自定义界面。
2025-06-17 15:29:54 +08:00
何冠峰
06a50a049e add mini game sample 2025-06-13 18:31:05 +08:00
何冠峰
6f049e2427 add mini game sample
小游戏扩展库独立
2025-06-13 18:19:35 +08:00
何冠峰
01c08a46ab fix #564 2025-06-13 17:39:30 +08:00
何冠峰
31dc5b494d fix #569 2025-06-13 17:25:13 +08:00
何冠峰
18e74e906e fix #551 2025-06-13 17:18:38 +08:00
何冠峰
4f62b249b4 update TableView
增加AssetObjectCell类
2025-05-19 16:25:16 +08:00
何冠峰
fe7f9bff08 fix #552 2025-05-15 15:38:13 +08:00
何冠峰
e71077f294 fix space shooter quit game error
修复太空战机DEMO在退出运行模式时的报错。
2025-05-13 17:53:17 +08:00
163 changed files with 1622 additions and 636 deletions

View File

@@ -2,6 +2,42 @@
All notable changes to this package will be documented in this file.
## [2.3.10] - 2025-06-17
### Improvements
- 小游戏扩展库已经独立,可以单独导入到项目工程。
- 编辑器里的TableView视图新增了AssetObjectCell类。
- (#552) 微信小游戏文件系统类增加了URL合法性的初始化检测机制。
- (#566) 重构了资源构建页面,方便扩展自定义界面。
- (#573) 完善了AssetDependencyDB的输出日志可以正确输出丢失的引用资产信息。
### Fixed
- 修复太空战机DEMO在退出运行模式时的报错。
- (#551) 修复了Unity2019, Unity2020的代码兼容性报错。
- (#569) 修复了TVOS平台的兼容问题。
- (#564) 修复了TiktokFileSystem文件系统里appendTimeTicks无效的问题。
### Added
- (#562) 新增了解密方法。
```csharp
public interface IDecryptionServices
{
/// <summary>
/// 后备方式获取解密的资源包对象
/// 注意:当正常解密方法失败后,会触发后备加载!
/// 说明建议通过LoadFromMemory()方法加载资源对象作为保底机制。
/// issues : https://github.com/tuyoogame/YooAsset/issues/562
/// </summary>
DecryptResult LoadAssetBundleFallback(DecryptFileInfo fileInfo);
}
```
## [2.3.9] - 2025-05-13
### Improvements

View File

@@ -196,6 +196,32 @@ namespace YooAsset.Editor
}
}
/// <summary>
/// 导入单个报告对象
/// </summary>
public void ImportSingleReprotFile(ScanReport report)
{
_reportCombiner = new ScanReportCombiner();
try
{
_reportCombiner.Combine(report);
// 刷新页面
RefreshToolbar();
FillTableView();
RebuildView();
}
catch (System.Exception e)
{
_reportCombiner = null;
_titleLabel.text = "导入报告失败!";
_descLabel.text = e.Message;
UnityEngine.Debug.LogError(e.StackTrace);
}
}
private void ImportSingleBtn_clicked()
{
string selectFilePath = EditorUtility.OpenFilePanel("导入报告", _lastestOpenFolder, "json");
@@ -446,15 +472,31 @@ namespace YooAsset.Editor
var column = new TableColumn(header.HeaderTitle, header.HeaderTitle, columnStyle);
column.MakeCell = () =>
{
var label = new Label();
label.style.marginLeft = 3f;
label.style.unityTextAlign = TextAnchor.MiddleLeft;
return label;
if (header.HeaderType == EHeaderType.AssetObject)
{
var objectFiled = new ObjectField();
return objectFiled;
}
else
{
var label = new Label();
label.style.marginLeft = 3f;
label.style.unityTextAlign = TextAnchor.MiddleLeft;
return label;
}
};
column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
if (header.HeaderType == EHeaderType.AssetObject)
{
var objectFiled = element as ObjectField;
objectFiled.value = (UnityEngine.Object)cell.GetDisplayObject();
}
else
{
var infoLabel = element as Label;
infoLabel.text = (string)cell.GetDisplayObject();
}
};
_elementTableView.AddColumn(column);
}
@@ -480,6 +522,10 @@ namespace YooAsset.Editor
{
tableData.AddAssetPathCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.AssetObject)
{
tableData.AddAssetObjectCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.StringValue)
{
tableData.AddStringValueCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);

View File

@@ -8,6 +8,11 @@ namespace YooAsset.Editor
/// </summary>
AssetPath,
/// <summary>
/// 资源对象
/// </summary>
AssetObject,
/// <summary>
/// 字符串
/// </summary>

View File

@@ -126,6 +126,12 @@ namespace YooAsset.Editor
if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset path : {value}");
}
else if (HeaderType == EHeaderType.AssetObject)
{
string guid = AssetDatabase.AssetPathToGUID(value);
if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset object : {value}");
}
else if (HeaderType == EHeaderType.DoubleValue)
{
if (double.TryParse(value, out double doubleValue) == false)

View File

@@ -46,7 +46,7 @@ namespace YooAsset.Editor
}
catch (Exception e)
{
return new ScannerResult(e.Message);
return new ScannerResult(e.StackTrace);
}
}

View File

@@ -52,7 +52,7 @@ namespace YooAsset.Editor
if (Succeed)
{
var reproterWindow = AssetArtReporterWindow.OpenWindow();
reproterWindow.ImportSingleReprotFile(ReprotFilePath);
reproterWindow.ImportSingleReprotFile(Report);
}
}
}

View File

@@ -6,97 +6,110 @@ namespace YooAsset.Editor
{
public static class AssetBundleBuilderSetting
{
// EBuildPipeline
public static EBuildPipeline GetPackageBuildPipeline(string packageName)
// BuildPipelineName
public static string GetPackageBuildPipeline(string packageName)
{
string key = $"{Application.productName}_{packageName}_{nameof(EBuildPipeline)}";
return (EBuildPipeline)EditorPrefs.GetInt(key, (int)EBuildPipeline.BuiltinBuildPipeline);
string key = $"{Application.productName}_{packageName}_BuildPipelineName";
string defaultValue = EBuildPipeline.ScriptableBuildPipeline.ToString();
return EditorPrefs.GetString(key, defaultValue);
}
public static void SetPackageBuildPipeline(string packageName, EBuildPipeline buildPipeline)
public static void SetPackageBuildPipeline(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{nameof(EBuildPipeline)}";
EditorPrefs.SetInt(key, (int)buildPipeline);
string key = $"{Application.productName}_{packageName}_BuildPipelineName";
EditorPrefs.SetString(key, buildPipeline);
}
// ECompressOption
public static ECompressOption GetPackageCompressOption(string packageName, EBuildPipeline buildPipeline)
public static ECompressOption GetPackageCompressOption(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
return (ECompressOption)EditorPrefs.GetInt(key, (int)ECompressOption.LZ4);
}
public static void SetPackageCompressOption(string packageName, EBuildPipeline buildPipeline, ECompressOption compressOption)
public static void SetPackageCompressOption(string packageName, string buildPipeline, ECompressOption compressOption)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(ECompressOption)}";
EditorPrefs.SetInt(key, (int)compressOption);
}
// EFileNameStyle
public static EFileNameStyle GetPackageFileNameStyle(string packageName, EBuildPipeline buildPipeline)
public static EFileNameStyle GetPackageFileNameStyle(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
return (EFileNameStyle)EditorPrefs.GetInt(key, (int)EFileNameStyle.HashName);
}
public static void SetPackageFileNameStyle(string packageName, EBuildPipeline buildPipeline, EFileNameStyle fileNameStyle)
public static void SetPackageFileNameStyle(string packageName, string buildPipeline, EFileNameStyle fileNameStyle)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EFileNameStyle)}";
EditorPrefs.SetInt(key, (int)fileNameStyle);
}
// EBuildinFileCopyOption
public static EBuildinFileCopyOption GetPackageBuildinFileCopyOption(string packageName, EBuildPipeline buildPipeline)
public static EBuildinFileCopyOption GetPackageBuildinFileCopyOption(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
return (EBuildinFileCopyOption)EditorPrefs.GetInt(key, (int)EBuildinFileCopyOption.None);
}
public static void SetPackageBuildinFileCopyOption(string packageName, EBuildPipeline buildPipeline, EBuildinFileCopyOption buildinFileCopyOption)
public static void SetPackageBuildinFileCopyOption(string packageName, string buildPipeline, EBuildinFileCopyOption buildinFileCopyOption)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_{nameof(EBuildinFileCopyOption)}";
EditorPrefs.SetInt(key, (int)buildinFileCopyOption);
}
// BuildFileCopyParams
public static string GetPackageBuildinFileCopyParams(string packageName, EBuildPipeline buildPipeline)
public static string GetPackageBuildinFileCopyParams(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
return EditorPrefs.GetString(key, string.Empty);
}
public static void SetPackageBuildinFileCopyParams(string packageName, EBuildPipeline buildPipeline, string buildinFileCopyParams)
public static void SetPackageBuildinFileCopyParams(string packageName, string buildPipeline, string buildinFileCopyParams)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_BuildFileCopyParams";
EditorPrefs.SetString(key, buildinFileCopyParams);
}
// EncyptionClassName
public static string GetPackageEncyptionClassName(string packageName, EBuildPipeline buildPipeline)
// EncyptionServicesClassName
public static string GetPackageEncyptionServicesClassName(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionClassName";
return EditorPrefs.GetString(key, string.Empty);
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(EncryptionNone).FullName}");
}
public static void SetPackageEncyptionClassName(string packageName, EBuildPipeline buildPipeline, string encyptionClassName)
public static void SetPackageEncyptionServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionClassName";
string key = $"{Application.productName}_{packageName}_{buildPipeline}_EncyptionServicesClassName";
EditorPrefs.SetString(key, encyptionClassName);
}
// ManifestServicesClassName
public static string GetPackageManifestServicesClassName(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestServicesClassName";
return EditorPrefs.GetString(key, $"{typeof(ManifestNone).FullName}");
}
public static void SetPackageManifestServicesClassName(string packageName, string buildPipeline, string encyptionClassName)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ManifestServicesClassName";
EditorPrefs.SetString(key, encyptionClassName);
}
// ClearBuildCache
public static bool GetPackageClearBuildCache(string packageName, EBuildPipeline buildPipeline)
public static bool GetPackageClearBuildCache(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ClearBuildCache";
return EditorPrefs.GetInt(key, 0) > 0;
}
public static void SetPackageClearBuildCache(string packageName, EBuildPipeline buildPipeline, bool clearBuildCache)
public static void SetPackageClearBuildCache(string packageName, string buildPipeline, bool clearBuildCache)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_ClearBuildCache";
EditorPrefs.SetInt(key, clearBuildCache ? 1 : 0);
}
// UseAssetDependencyDB
public static bool GetPackageUseAssetDependencyDB(string packageName, EBuildPipeline buildPipeline)
public static bool GetPackageUseAssetDependencyDB(string packageName, string buildPipeline)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_UseAssetDependencyDB";
return EditorPrefs.GetInt(key, 0) > 0;
}
public static void SetPackageUseAssetDependencyDB(string packageName, EBuildPipeline buildPipeline, bool useAssetDependencyDB)
public static void SetPackageUseAssetDependencyDB(string packageName, string buildPipeline, bool useAssetDependencyDB)
{
string key = $"{Application.productName}_{packageName}_{buildPipeline}_UseAssetDependencyDB";
EditorPrefs.SetInt(key, useAssetDependencyDB ? 1 : 0);

View File

@@ -19,7 +19,9 @@ namespace YooAsset.Editor
}
private string _buildPackage;
private EBuildPipeline _buildPipeline;
private string _buildPipeline;
private Dictionary<string, Type> _viewClassDic = new Dictionary<string, Type>(10);
private Toolbar _toolbar;
private ToolbarMenu _packageMenu;
@@ -69,11 +71,23 @@ namespace YooAsset.Editor
{
_pipelineMenu = new ToolbarMenu();
_pipelineMenu.style.width = 200;
_pipelineMenu.menu.AppendAction(EBuildPipeline.EditorSimulateBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.EditorSimulateBuildPipeline);
_pipelineMenu.menu.AppendAction(EBuildPipeline.BuiltinBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.BuiltinBuildPipeline);
_pipelineMenu.menu.AppendAction(EBuildPipeline.ScriptableBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.ScriptableBuildPipeline);
_pipelineMenu.menu.AppendAction(EBuildPipeline.RawFileBuildPipeline.ToString(), PipelineMenuAction, PipelineMenuFun, EBuildPipeline.RawFileBuildPipeline);
_toolbar.Add(_pipelineMenu);
var viewerClassTypes = EditorTools.GetAssignableTypes(typeof(BuildPipelineViewerBase));
foreach (var classType in viewerClassTypes)
{
var buildPipelineAttribute = EditorTools.GetAttribute<BuildPipelineAttribute>(classType);
string pipelineName = buildPipelineAttribute.PipelineName;
if (_viewClassDic.ContainsKey(pipelineName))
{
Debug.LogWarning($"The pipeline has already exist : {pipelineName}");
}
else
{
_viewClassDic.Add(pipelineName, classType);
_pipelineMenu.menu.AppendAction(pipelineName, PipelineMenuAction, PipelineMenuFun);
}
}
}
RefreshBuildPipelineView();
@@ -91,28 +105,18 @@ namespace YooAsset.Editor
_buildPipeline = AssetBundleBuilderSetting.GetPackageBuildPipeline(_buildPackage);
_packageMenu.text = _buildPackage;
_pipelineMenu.text = _buildPipeline.ToString();
_pipelineMenu.text = _buildPipeline;
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
if (_buildPipeline == EBuildPipeline.EditorSimulateBuildPipeline)
if (_viewClassDic.TryGetValue(_buildPipeline, out Type value))
{
var viewer = new EditorSimulateBuildPipelineViewer(_buildPackage, buildTarget, _container);
}
else if (_buildPipeline == EBuildPipeline.BuiltinBuildPipeline)
{
var viewer = new BuiltinBuildPipelineViewer(_buildPackage, buildTarget, _container);
}
else if (_buildPipeline == EBuildPipeline.ScriptableBuildPipeline)
{
var viewer = new ScriptableBuildPipelineViewer(_buildPackage, buildTarget, _container);
}
else if (_buildPipeline == EBuildPipeline.RawFileBuildPipeline)
{
var viewer = new RawfileBuildpipelineViewer(_buildPackage, buildTarget, _container);
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
var viewer = Activator.CreateInstance(value) as BuildPipelineViewerBase;
viewer.InitView(_buildPackage, _buildPipeline, buildTarget);
viewer.CreateView(_container);
}
else
{
throw new System.NotImplementedException(_buildPipeline.ToString());
Debug.LogError($"Not found build pipeline : {_buildPipeline}");
}
}
private List<string> GetBuildPackageNames()
@@ -145,18 +149,16 @@ namespace YooAsset.Editor
private void PipelineMenuAction(DropdownMenuAction action)
{
var pipelineType = (EBuildPipeline)action.userData;
if (_buildPipeline != pipelineType)
if (_buildPipeline != action.name)
{
_buildPipeline = pipelineType;
AssetBundleBuilderSetting.SetPackageBuildPipeline(_buildPackage, pipelineType);
_buildPipeline = action.name;
AssetBundleBuilderSetting.SetPackageBuildPipeline(_buildPackage, _buildPipeline);
RefreshBuildPipelineView();
}
}
private DropdownMenuAction.Status PipelineMenuFun(DropdownMenuAction action)
{
var pipelineType = (EBuildPipeline)action.userData;
if (_buildPipeline == pipelineType)
if (_buildPipeline == action.name)
return DropdownMenuAction.Status.Checked;
else
return DropdownMenuAction.Status.Normal;

View File

@@ -98,6 +98,11 @@ namespace YooAsset.Editor
/// </summary>
public IEncryptionServices EncryptionServices;
/// <summary>
/// 资源清单服务类
/// </summary>
public IManifestServices ManifestServices;
private string _pipelineOutputDirectory = string.Empty;
private string _packageOutputDirectory = string.Empty;

View File

@@ -14,7 +14,8 @@ namespace YooAsset.Editor
{
string buildinRootDirectory = buildParametersContext.GetBuildinRootDirectory();
string buildPackageName = buildParametersContext.Parameters.PackageName;
DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(buildPackageName, buildinRootDirectory);
var manifestServices = buildParametersContext.Parameters.ManifestServices;
DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(manifestServices, buildPackageName, buildinRootDirectory);
// 刷新目录
AssetDatabase.Refresh();

View File

@@ -58,7 +58,7 @@ namespace YooAsset.Editor
if (processBundleDepends)
ProcessBuiltinBundleDependency(context, manifest);
// 创建补丁清单文本文件
// 创建资源清单文本文件
{
string fileName = YooAssetSettingsData.GetManifestJsonFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
@@ -66,18 +66,18 @@ namespace YooAsset.Editor
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);
ManifestTools.SerializeToBinary(packagePath, manifest, buildParameters.ManifestServices);
packageHash = HashUtility.FileCRC32(packagePath);
BuildLogger.Log($"Create package manifest file: {packagePath}");
}
// 创建补丁清单哈希文件
// 创建资源清单哈希文件
{
string fileName = YooAssetSettingsData.GetPackageHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
string filePath = $"{packageOutputDirectory}/{fileName}";
@@ -85,7 +85,7 @@ namespace YooAsset.Editor
BuildLogger.Log($"Create package manifest hash file: {filePath}");
}
// 创建补丁清单版本文件
// 创建资源清单版本文件
{
string fileName = YooAssetSettingsData.GetPackageVersionFileName(buildParameters.PackageName);
string filePath = $"{packageOutputDirectory}/{fileName}";
@@ -97,7 +97,7 @@ namespace YooAsset.Editor
{
ManifestContext manifestContext = new ManifestContext();
byte[] bytesData = FileUtility.ReadAllBytes(packagePath);
manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData);
manifestContext.Manifest = ManifestTools.DeserializeFromBinary(bytesData, buildParameters.ManifestServices);
context.SetContextObject(manifestContext);
}
}

View File

@@ -43,7 +43,8 @@ namespace YooAsset.Editor
buildReport.Summary.EnableSharePackRule = buildParameters.EnableSharePackRule;
buildReport.Summary.SingleReferencedPackAlone = buildParameters.SingleReferencedPackAlone;
buildReport.Summary.FileNameStyle = buildParameters.FileNameStyle;
buildReport.Summary.EncryptionClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName;
buildReport.Summary.EncryptionServicesClassName = buildParameters.EncryptionServices == null ? "null" : buildParameters.EncryptionServices.GetType().FullName;
buildReport.Summary.ManifestServicesClassName = buildParameters.ManifestServices == null ? "null" : buildParameters.ManifestServices.GetType().FullName;
if (buildParameters is BuiltinBuildParameters)
{
var builtinBuildParameters = buildParameters as BuiltinBuildParameters;

View File

@@ -0,0 +1,15 @@

namespace YooAsset.Editor
{
public class ManifestNone : IManifestServices
{
public byte[] ProcessManifest(byte[] fileData)
{
return fileData;
}
public byte[] RestoreManifest(byte[] fileData)
{
return fileData;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 446513b0ea9f5d445ade0cfb09c5073b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +1,13 @@

using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public interface IBuildPipeline
{
/// <summary>
/// 运行构建任务
/// </summary>
BuildResult Run(BuildParameters buildParameters, bool enableLog);
}
}

View File

@@ -0,0 +1,14 @@
using System;
namespace YooAsset.Editor
{
public class BuildPipelineAttribute : Attribute
{
public string PipelineName;
public BuildPipelineAttribute(string name)
{
this.PipelineName = name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90d865a5cede7ae43a5fdabdc20af0fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,211 +12,224 @@ namespace YooAsset.Editor
{
internal abstract class BuildPipelineViewerBase
{
private const int StyleWidth = 400;
private const int LabelMinWidth = 180;
protected const int StyleWidth = 400;
protected const int LabelMinWidth = 190;
protected readonly string PackageName;
protected readonly BuildTarget BuildTarget;
protected readonly EBuildPipeline BuildPipeline;
protected TemplateContainer Root;
protected string PackageName { private set; get; }
protected string PipelineName { private set; get; }
protected BuildTarget BuildTarget { private set; get; }
private TextField _buildOutputField;
private TextField _buildVersionField;
private PopupField<Enum> _buildModeField;
private PopupField<Type> _encryptionField;
private EnumField _compressionField;
private EnumField _outputNameStyleField;
private EnumField _copyBuildinFileOptionField;
private TextField _copyBuildinFileTagsField;
private Toggle _clearBuildCacheToggle;
private Toggle _useAssetDependencyDBToggle;
public BuildPipelineViewerBase(string packageName, EBuildPipeline buildPipeline, BuildTarget buildTarget, VisualElement parent)
/// <summary>
/// 初始化视图
/// </summary>
public void InitView(string packageName, string pipelineName, BuildTarget buildTarget)
{
PackageName = packageName;
PipelineName = pipelineName;
BuildTarget = buildTarget;
BuildPipeline = buildPipeline;
CreateView(parent);
RefreshView();
}
private void CreateView(VisualElement parent)
{
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<BuildPipelineViewerBase>();
if (visualAsset == null)
return;
Root = visualAsset.CloneTree();
Root.style.flexGrow = 1f;
parent.Add(Root);
// 输出目录
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
_buildOutputField = Root.Q<TextField>("BuildOutput");
_buildOutputField.SetValueWithoutNotify(defaultOutputRoot);
_buildOutputField.SetEnabled(false);
// 构建版本
_buildVersionField = Root.Q<TextField>("BuildVersion");
_buildVersionField.style.width = StyleWidth;
_buildVersionField.SetValueWithoutNotify(GetDefaultPackageVersion());
// 加密方法
{
var encryptionContainer = Root.Q("EncryptionContainer");
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
if (encryptionClassTypes.Count > 0)
{
var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(PackageName, BuildPipeline);
int defaultIndex = encryptionClassTypes.FindIndex(x => x.FullName.Equals(encyptionClassName));
if (defaultIndex < 0)
defaultIndex = 0;
_encryptionField = new PopupField<Type>(encryptionClassTypes, defaultIndex);
_encryptionField.label = "Encryption";
_encryptionField.style.width = StyleWidth;
_encryptionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageEncyptionClassName(PackageName, BuildPipeline, _encryptionField.value.FullName);
});
encryptionContainer.Add(_encryptionField);
}
else
{
_encryptionField = new PopupField<Type>();
_encryptionField.label = "Encryption";
_encryptionField.style.width = StyleWidth;
encryptionContainer.Add(_encryptionField);
}
}
// 压缩方式选项
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
_compressionField = Root.Q<EnumField>("Compression");
_compressionField.Init(compressOption);
_compressionField.SetValueWithoutNotify(compressOption);
_compressionField.style.width = StyleWidth;
_compressionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageCompressOption(PackageName, BuildPipeline, (ECompressOption)_compressionField.value);
});
// 输出文件名称样式
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
_outputNameStyleField = Root.Q<EnumField>("FileNameStyle");
_outputNameStyleField.Init(fileNameStyle);
_outputNameStyleField.SetValueWithoutNotify(fileNameStyle);
_outputNameStyleField.style.width = StyleWidth;
_outputNameStyleField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageFileNameStyle(PackageName, BuildPipeline, (EFileNameStyle)_outputNameStyleField.value);
});
// 首包文件拷贝选项
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
_copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
_copyBuildinFileOptionField.Init(buildinFileCopyOption);
_copyBuildinFileOptionField.SetValueWithoutNotify(buildinFileCopyOption);
_copyBuildinFileOptionField.style.width = StyleWidth;
_copyBuildinFileOptionField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyOption(PackageName, BuildPipeline, (EBuildinFileCopyOption)_copyBuildinFileOptionField.value);
RefreshView();
});
// 首包文件拷贝参数
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
_copyBuildinFileTagsField = Root.Q<TextField>("CopyBuildinFileParam");
_copyBuildinFileTagsField.SetValueWithoutNotify(buildinFileCopyParams);
_copyBuildinFileTagsField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyParams(PackageName, BuildPipeline, _copyBuildinFileTagsField.value);
});
// 清理构建缓存
bool clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline);
_clearBuildCacheToggle = Root.Q<Toggle>("ClearBuildCache");
_clearBuildCacheToggle.SetValueWithoutNotify(clearBuildCache);
_clearBuildCacheToggle.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageClearBuildCache(PackageName, BuildPipeline, _clearBuildCacheToggle.value);
});
// 使用资源依赖数据库
bool useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline);
_useAssetDependencyDBToggle = Root.Q<Toggle>("UseAssetDependency");
_useAssetDependencyDBToggle.SetValueWithoutNotify(useAssetDependencyDB);
_useAssetDependencyDBToggle.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageUseAssetDependencyDB(PackageName, BuildPipeline, _useAssetDependencyDBToggle.value);
});
// 对齐文本间距
UIElementsTools.SetElementLabelMinWidth(_buildOutputField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_buildVersionField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_compressionField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_encryptionField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_outputNameStyleField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_copyBuildinFileOptionField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_copyBuildinFileTagsField, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_clearBuildCacheToggle, LabelMinWidth);
UIElementsTools.SetElementLabelMinWidth(_useAssetDependencyDBToggle, LabelMinWidth);
// 构建按钮
var buildButton = Root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked;
}
private void RefreshView()
{
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
bool tagsFiledVisible = buildinFileCopyOption == EBuildinFileCopyOption.ClearAndCopyByTags || buildinFileCopyOption == EBuildinFileCopyOption.OnlyCopyByTags;
_copyBuildinFileTagsField.visible = tagsFiledVisible;
}
private void BuildButton_clicked()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建任务
/// 创建视图
/// </summary>
protected abstract void ExecuteBuild();
public abstract void CreateView(VisualElement parent);
/// <summary>
/// 获取构建版本
/// 获取默认版本
/// </summary>
protected string GetPackageVersion()
protected virtual string GetDefaultPackageVersion()
{
return _buildVersionField.value;
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
}
/// <summary>
/// 创建加密类实例
/// 创建资源加密服务类实例
/// </summary>
protected IEncryptionServices CreateEncryptionInstance()
protected IEncryptionServices CreateEncryptionServicesInstance()
{
var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionClassName(PackageName, BuildPipeline);
var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName);
var classTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
var classType = classTypes.Find(x => x.FullName.Equals(className));
if (classType != null)
return (IEncryptionServices)Activator.CreateInstance(classType);
else
return null;
}
private string GetDefaultPackageVersion()
/// <summary>
/// 创建资源清单服务类实例
/// </summary>
protected IManifestServices CreateManifestServicesInstance()
{
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
var className = AssetBundleBuilderSetting.GetPackageManifestServicesClassName(PackageName, PipelineName);
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestServices));
var classType = classTypes.Find(x => x.FullName.Equals(className));
if (classType != null)
return (IManifestServices)Activator.CreateInstance(classType);
else
return null;
}
#region UI元素通用处理方法
protected void SetBuildOutputField(TextField textField)
{
// 输出目录
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
textField.SetValueWithoutNotify(defaultOutputRoot);
textField.SetEnabled(false);
UIElementsTools.SetElementLabelMinWidth(textField, LabelMinWidth);
}
protected void SetBuildVersionField(TextField textField)
{
// 构建版本
textField.style.width = StyleWidth;
textField.SetValueWithoutNotify(GetDefaultPackageVersion());
UIElementsTools.SetElementLabelMinWidth(textField, LabelMinWidth);
}
protected void SetCompressionField(EnumField enumField)
{
// 压缩方式选项
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, PipelineName);
enumField.Init(compressOption);
enumField.SetValueWithoutNotify(compressOption);
enumField.style.width = StyleWidth;
enumField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageCompressOption(PackageName, PipelineName, (ECompressOption)enumField.value);
});
UIElementsTools.SetElementLabelMinWidth(enumField, LabelMinWidth);
}
protected void SetOutputNameStyleField(EnumField enumField)
{
// 输出文件名称样式
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, PipelineName);
enumField.Init(fileNameStyle);
enumField.SetValueWithoutNotify(fileNameStyle);
enumField.style.width = StyleWidth;
enumField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageFileNameStyle(PackageName, PipelineName, (EFileNameStyle)enumField.value);
});
UIElementsTools.SetElementLabelMinWidth(enumField, LabelMinWidth);
}
protected void SetCopyBuildinFileOptionField(EnumField enumField, TextField tagField)
{
// 首包文件拷贝选项
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
enumField.Init(buildinFileCopyOption);
enumField.SetValueWithoutNotify(buildinFileCopyOption);
enumField.style.width = StyleWidth;
enumField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyOption(PackageName, PipelineName, (EBuildinFileCopyOption)enumField.value);
// 设置内置资源标签显隐
SetCopyBuildinFileTagsVisible(tagField);
});
UIElementsTools.SetElementLabelMinWidth(enumField, LabelMinWidth);
}
protected void SetCopyBuildinFileTagsVisible(TextField tagField)
{
var option = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
tagField.visible = option == EBuildinFileCopyOption.ClearAndCopyByTags || option == EBuildinFileCopyOption.OnlyCopyByTags;
}
protected void SetCopyBuildinFileTagsField(TextField textField)
{
// 首包文件拷贝参数
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, PipelineName);
textField.SetValueWithoutNotify(buildinFileCopyParams);
textField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageBuildinFileCopyParams(PackageName, PipelineName, textField.value);
});
UIElementsTools.SetElementLabelMinWidth(textField, LabelMinWidth);
}
protected void SetClearBuildCacheToggle(Toggle toggle)
{
// 清理构建缓存
bool clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
toggle.SetValueWithoutNotify(clearBuildCache);
toggle.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageClearBuildCache(PackageName, PipelineName, toggle.value);
});
UIElementsTools.SetElementLabelMinWidth(toggle, LabelMinWidth);
}
protected void SetUseAssetDependencyDBToggle(Toggle toggle)
{
// 使用资源依赖数据库
bool useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
toggle.SetValueWithoutNotify(useAssetDependencyDB);
toggle.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageUseAssetDependencyDB(PackageName, PipelineName, toggle.value);
});
UIElementsTools.SetElementLabelMinWidth(toggle, LabelMinWidth);
}
protected PopupField<Type> CreateEncryptionServicesField(VisualElement container)
{
// 加密服务类
var classTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
if (classTypes.Count > 0)
{
var className = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, PipelineName);
int defaultIndex = classTypes.FindIndex(x => x.FullName.Equals(className));
if (defaultIndex < 0)
defaultIndex = 0;
var popupField = new PopupField<Type>(classTypes, defaultIndex);
popupField.label = "Encryption Services";
popupField.style.width = StyleWidth;
popupField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageEncyptionServicesClassName(PackageName, PipelineName, popupField.value.FullName);
});
container.Add(popupField);
UIElementsTools.SetElementLabelMinWidth(popupField, LabelMinWidth);
return popupField;
}
else
{
var popupField = new PopupField<Type>();
popupField.label = "Encryption Services";
popupField.style.width = StyleWidth;
container.Add(popupField);
UIElementsTools.SetElementLabelMinWidth(popupField, LabelMinWidth);
return popupField;
}
}
protected PopupField<Type> CreateManifestServicesField(VisualElement container)
{
// 清单服务类
var classTypes = EditorTools.GetAssignableTypes(typeof(IManifestServices));
if (classTypes.Count > 0)
{
var className = AssetBundleBuilderSetting.GetPackageManifestServicesClassName(PackageName, PipelineName);
int defaultIndex = classTypes.FindIndex(x => x.FullName.Equals(className));
if (defaultIndex < 0)
defaultIndex = 0;
var popupField = new PopupField<Type>(classTypes, defaultIndex);
popupField.label = "Manifest Services";
popupField.style.width = StyleWidth;
popupField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSetting.SetPackageManifestServicesClassName(PackageName, PipelineName, popupField.value.FullName);
});
container.Add(popupField);
UIElementsTools.SetElementLabelMinWidth(popupField, LabelMinWidth);
return popupField;
}
else
{
var popupField = new PopupField<Type>();
popupField.label = "Manifest Services";
popupField.style.width = StyleWidth;
container.Add(popupField);
UIElementsTools.SetElementLabelMinWidth(popupField, LabelMinWidth);
return popupField;
}
}
#endregion
}
}
#endif

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5280dfac6a481ee429c769ba5688c9d2
guid: e2e1fae9b05cc554e9ebfee01f2b9333
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,132 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
[BuildPipelineAttribute(nameof(EBuildPipeline.BuiltinBuildPipeline))]
internal class BuiltinBuildPipelineViewer : BuildPipelineViewerBase
{
protected TemplateContainer Root;
protected TextField _buildOutputField;
protected TextField _buildVersionField;
protected PopupField<Type> _encryptionServicesField;
protected PopupField<Type> _manifestServicesField;
protected EnumField _compressionField;
protected EnumField _outputNameStyleField;
protected EnumField _copyBuildinFileOptionField;
protected TextField _copyBuildinFileTagsField;
protected Toggle _clearBuildCacheToggle;
protected Toggle _useAssetDependencyDBToggle;
public override void CreateView(VisualElement parent)
{
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<BuiltinBuildPipelineViewer>();
if (visualAsset == null)
return;
Root = visualAsset.CloneTree();
Root.style.flexGrow = 1f;
parent.Add(Root);
// 输出目录
_buildOutputField = Root.Q<TextField>("BuildOutput");
SetBuildOutputField(_buildOutputField);
// 构建版本
_buildVersionField = Root.Q<TextField>("BuildVersion");
SetBuildVersionField(_buildVersionField);
// 服务类
var popupContainer = Root.Q("PopupContainer");
_encryptionServicesField = CreateEncryptionServicesField(popupContainer);
_manifestServicesField = CreateManifestServicesField(popupContainer);
// 压缩方式选项
_compressionField = Root.Q<EnumField>("Compression");
SetCompressionField(_compressionField);
// 输出文件名称样式
_outputNameStyleField = Root.Q<EnumField>("FileNameStyle");
SetOutputNameStyleField(_outputNameStyleField);
// 首包文件拷贝参数
_copyBuildinFileTagsField = Root.Q<TextField>("CopyBuildinFileParam");
SetCopyBuildinFileTagsField(_copyBuildinFileTagsField);
SetCopyBuildinFileTagsVisible(_copyBuildinFileTagsField);
// 首包文件拷贝选项
_copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
SetCopyBuildinFileOptionField(_copyBuildinFileOptionField, _copyBuildinFileTagsField);
// 清理构建缓存
_clearBuildCacheToggle = Root.Q<Toggle>("ClearBuildCache");
SetClearBuildCacheToggle(_clearBuildCacheToggle);
// 使用资源依赖数据库
_useAssetDependencyDBToggle = Root.Q<Toggle>("UseAssetDependency");
SetUseAssetDependencyDBToggle(_useAssetDependencyDBToggle);
// 构建按钮
var buildButton = Root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked;
}
private void BuildButton_clicked()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建
/// </summary>
protected virtual void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, PipelineName);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, PipelineName);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, PipelineName);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = PipelineName.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = _buildVersionField.value;
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.ManifestServices = CreateManifestServicesInstance();
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -4,7 +4,7 @@
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" />
<ui:Toggle label="Clear Build Cache" name="ClearBuildCache" />
<ui:Toggle label="Use Asset Depend DB" name="UseAssetDependency" />
<ui:VisualElement name="EncryptionContainer" style="height: 24px;" />
<ui:VisualElement name="PopupContainer" style="flex-grow: 1;" />
<uie:EnumField label="Compression" value="Center" name="Compression" />
<uie:EnumField label="File Name Style" value="Center" name="FileNameStyle" />
<uie:EnumField label="Copy Buildin File Option" value="Center" name="CopyBuildinFileOption" />

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 86d0df373d425b449a3bbc42b4b2e5bb
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -1,57 +0,0 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
internal class BuiltinBuildPipelineViewer : BuildPipelineViewerBase
{
public BuiltinBuildPipelineViewer(string packageName, BuildTarget buildTarget, VisualElement parent)
: base(packageName, EBuildPipeline.BuiltinBuildPipeline, buildTarget, parent)
{
}
/// <summary>
/// 执行构建
/// </summary>
protected override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline);
BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = BuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion();
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionInstance();
BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 33b6cb215b1d7bb4888cb3455b500399
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
[BuildPipelineAttribute(nameof(EBuildPipeline.EditorSimulateBuildPipeline))]
internal class EditorSimulateBuildPipelineViewer : BuildPipelineViewerBase
{
protected TemplateContainer Root;
protected TextField _buildOutputField;
protected TextField _buildVersionField;
public override void CreateView(VisualElement parent)
{
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<EditorSimulateBuildPipelineViewer>();
if (visualAsset == null)
return;
Root = visualAsset.CloneTree();
Root.style.flexGrow = 1f;
parent.Add(Root);
// 输出目录
_buildOutputField = Root.Q<TextField>("BuildOutput");
SetBuildOutputField(_buildOutputField);
// 构建版本
_buildVersionField = Root.Q<TextField>("BuildVersion");
SetBuildVersionField(_buildVersionField);
// 构建按钮
var buildButton = Root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked;
}
private void BuildButton_clicked()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建
/// </summary>
protected virtual void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, PipelineName);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, PipelineName);
EditorSimulateBuildParameters buildParameters = new EditorSimulateBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = PipelineName.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.VirtualBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = _buildVersionField.value;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
EditorSimulateBuildPipeline pipeline = new EditorSimulateBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement name="BuildContainer">
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" />
<ui:VisualElement name="ExtensionContainer" />
<ui:Button text="Click Build" display-tooltip-when-elided="true" name="Build" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 90cc4546b2b8afe4e8c864c132a999a9
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -1,70 +0,0 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
internal class EditorSimulateBuildPipelineViewer : BuildPipelineViewerBase
{
public EditorSimulateBuildPipelineViewer(string packageName, BuildTarget buildTarget, VisualElement parent)
: base(packageName, EBuildPipeline.RawFileBuildPipeline, buildTarget, parent)
{
var compressionField = Root.Q<EnumField>("Compression");
UIElementsTools.SetElementVisible(compressionField, false);
var encryptionContainer = Root.Q<VisualElement>("EncryptionContainer");
UIElementsTools.SetElementVisible(encryptionContainer, false);
var fileNameStyleField = Root.Q<EnumField>("FileNameStyle");
UIElementsTools.SetElementVisible(fileNameStyleField, false);
var copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
UIElementsTools.SetElementVisible(copyBuildinFileOptionField, false);
var copyBuildinFileParamField = Root.Q<TextField>("CopyBuildinFileParam");
UIElementsTools.SetElementVisible(copyBuildinFileParamField, false);
var clearBuildCacheToggle = Root.Q<Toggle>("ClearBuildCache");
UIElementsTools.SetElementVisible(clearBuildCacheToggle, false);
var useAssetDependencyToggle = Root.Q<Toggle>("UseAssetDependency");
UIElementsTools.SetElementVisible(useAssetDependencyToggle, false);
}
/// <summary>
/// 执行构建
/// </summary>
protected override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
EditorSimulateBuildParameters buildParameters = new EditorSimulateBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = BuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.VirtualBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion();
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.EncryptionServices = CreateEncryptionInstance();
EditorSimulateBuildPipeline pipeline = new EditorSimulateBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 56adb3acd233fe5468af213a4c41de6a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,124 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
[BuildPipelineAttribute(nameof(EBuildPipeline.RawFileBuildPipeline))]
internal class RawfileBuildpipelineViewer : BuildPipelineViewerBase
{
protected TemplateContainer Root;
protected TextField _buildOutputField;
protected TextField _buildVersionField;
protected PopupField<Type> _encryptionServicesField;
protected PopupField<Type> _manifestServicesField;
protected EnumField _outputNameStyleField;
protected EnumField _copyBuildinFileOptionField;
protected TextField _copyBuildinFileTagsField;
protected Toggle _clearBuildCacheToggle;
protected Toggle _useAssetDependencyDBToggle;
public override void CreateView(VisualElement parent)
{
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<RawfileBuildpipelineViewer>();
if (visualAsset == null)
return;
Root = visualAsset.CloneTree();
Root.style.flexGrow = 1f;
parent.Add(Root);
// 输出目录
_buildOutputField = Root.Q<TextField>("BuildOutput");
SetBuildOutputField(_buildOutputField);
// 构建版本
_buildVersionField = Root.Q<TextField>("BuildVersion");
SetBuildVersionField(_buildVersionField);
// 加密方法
var popupContainer = Root.Q("PopupContainer");
_encryptionServicesField = CreateEncryptionServicesField(popupContainer);
_manifestServicesField = CreateManifestServicesField(popupContainer);
// 输出文件名称样式
_outputNameStyleField = Root.Q<EnumField>("FileNameStyle");
SetOutputNameStyleField(_outputNameStyleField);
// 首包文件拷贝参数
_copyBuildinFileTagsField = Root.Q<TextField>("CopyBuildinFileParam");
SetCopyBuildinFileTagsField(_copyBuildinFileTagsField);
SetCopyBuildinFileTagsVisible(_copyBuildinFileTagsField);
// 首包文件拷贝选项
_copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
SetCopyBuildinFileOptionField(_copyBuildinFileOptionField, _copyBuildinFileTagsField);
// 清理构建缓存
_clearBuildCacheToggle = Root.Q<Toggle>("ClearBuildCache");
SetClearBuildCacheToggle(_clearBuildCacheToggle);
// 使用资源依赖数据库
_useAssetDependencyDBToggle = Root.Q<Toggle>("UseAssetDependency");
SetUseAssetDependencyDBToggle(_useAssetDependencyDBToggle);
// 构建按钮
var buildButton = Root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked;
}
private void BuildButton_clicked()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建
/// </summary>
protected virtual void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, PipelineName);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, PipelineName);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
RawFileBuildParameters buildParameters = new RawFileBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = PipelineName.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.RawBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = _buildVersionField.value;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.ManifestServices = CreateManifestServicesInstance();
RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -0,0 +1,14 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement name="BuildContainer">
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" />
<ui:Toggle label="Clear Build Cache" name="ClearBuildCache" />
<ui:Toggle label="Use Asset Depend DB" name="UseAssetDependency" />
<ui:VisualElement name="PopupContainer" style="flex-grow: 1;" />
<uie:EnumField label="File Name Style" value="Center" name="FileNameStyle" />
<uie:EnumField label="Copy Buildin File Option" value="Center" name="CopyBuildinFileOption" />
<ui:TextField picking-mode="Ignore" label="Copy Buildin File Param" name="CopyBuildinFileParam" />
<ui:VisualElement name="ExtensionContainer" />
<ui:Button text="Click Build" display-tooltip-when-elided="true" name="Build" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8ed3387ab250c814e9797164c9a4b89a
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -1,56 +0,0 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
internal class RawfileBuildpipelineViewer : BuildPipelineViewerBase
{
public RawfileBuildpipelineViewer(string packageName, BuildTarget buildTarget, VisualElement parent)
: base(packageName, EBuildPipeline.RawFileBuildPipeline, buildTarget, parent)
{
var compressionField = Root.Q<EnumField>("Compression");
UIElementsTools.SetElementVisible(compressionField, false);
}
/// <summary>
/// 执行构建
/// </summary>
protected override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline);
RawFileBuildParameters buildParameters = new RawFileBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = BuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.RawBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion();
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.EncryptionServices = CreateEncryptionInstance();
RawFileBuildPipeline pipeline = new RawFileBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
}
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: be39d027dec0b2f41ab1dba7effb1a9c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
[BuildPipelineAttribute(nameof(EBuildPipeline.ScriptableBuildPipeline))]
internal class ScriptableBuildPipelineViewer : BuildPipelineViewerBase
{
protected TemplateContainer Root;
protected TextField _buildOutputField;
protected TextField _buildVersionField;
protected PopupField<Type> _encryptionServicesField;
protected PopupField<Type> _manifestServicesField;
protected EnumField _compressionField;
protected EnumField _outputNameStyleField;
protected EnumField _copyBuildinFileOptionField;
protected TextField _copyBuildinFileTagsField;
protected Toggle _clearBuildCacheToggle;
protected Toggle _useAssetDependencyDBToggle;
public override void CreateView(VisualElement parent)
{
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<ScriptableBuildPipelineViewer>();
if (visualAsset == null)
return;
Root = visualAsset.CloneTree();
Root.style.flexGrow = 1f;
parent.Add(Root);
// 输出目录
_buildOutputField = Root.Q<TextField>("BuildOutput");
SetBuildOutputField(_buildOutputField);
// 构建版本
_buildVersionField = Root.Q<TextField>("BuildVersion");
SetBuildVersionField(_buildVersionField);
// 加密方法
var popupContainer = Root.Q("PopupContainer");
_encryptionServicesField = CreateEncryptionServicesField(popupContainer);
_manifestServicesField = CreateManifestServicesField(popupContainer);
// 压缩方式选项
_compressionField = Root.Q<EnumField>("Compression");
SetCompressionField(_compressionField);
// 输出文件名称样式
_outputNameStyleField = Root.Q<EnumField>("FileNameStyle");
SetOutputNameStyleField(_outputNameStyleField);
// 首包文件拷贝参数
_copyBuildinFileTagsField = Root.Q<TextField>("CopyBuildinFileParam");
SetCopyBuildinFileTagsField(_copyBuildinFileTagsField);
SetCopyBuildinFileTagsVisible(_copyBuildinFileTagsField);
// 首包文件拷贝选项
_copyBuildinFileOptionField = Root.Q<EnumField>("CopyBuildinFileOption");
SetCopyBuildinFileOptionField(_copyBuildinFileOptionField, _copyBuildinFileTagsField);
// 清理构建缓存
_clearBuildCacheToggle = Root.Q<Toggle>("ClearBuildCache");
SetClearBuildCacheToggle(_clearBuildCacheToggle);
// 使用资源依赖数据库
_useAssetDependencyDBToggle = Root.Q<Toggle>("UseAssetDependency");
SetUseAssetDependencyDBToggle(_useAssetDependencyDBToggle);
// 构建按钮
var buildButton = Root.Q<Button>("Build");
buildButton.clicked += BuildButton_clicked;
}
private void BuildButton_clicked()
{
if (EditorUtility.DisplayDialog("提示", $"开始构建资源包[{PackageName}]", "Yes", "No"))
{
EditorTools.ClearUnityConsole();
EditorApplication.delayCall += ExecuteBuild;
}
else
{
Debug.LogWarning("[Build] 打包已经取消");
}
}
/// <summary>
/// 执行构建
/// </summary>
protected virtual void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, PipelineName);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, PipelineName);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, PipelineName);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, PipelineName);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, PipelineName);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, PipelineName);
var builtinShaderBundleName = GetBuiltinShaderBundleName();
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = PipelineName.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = _buildVersionField.value;
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
buildParameters.ManifestServices = CreateManifestServicesInstance();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
/// <summary>
/// 内置着色器资源包名称
/// 注意:和自动收集的着色器资源包名保持一致!
/// </summary>
protected string GetBuiltinShaderBundleName()
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
}
}
#endif

View File

@@ -0,0 +1,15 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
<ui:VisualElement name="BuildContainer">
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" />
<ui:Toggle label="Clear Build Cache" name="ClearBuildCache" />
<ui:Toggle label="Use Asset Depend DB" name="UseAssetDependency" />
<ui:VisualElement name="PopupContainer" style="flex-grow: 1;" />
<uie:EnumField label="Compression" value="Center" name="Compression" />
<uie:EnumField label="File Name Style" value="Center" name="FileNameStyle" />
<uie:EnumField label="Copy Buildin File Option" value="Center" name="CopyBuildinFileOption" />
<ui:TextField picking-mode="Ignore" label="Copy Buildin File Param" name="CopyBuildinFileParam" />
<ui:VisualElement name="ExtensionContainer" />
<ui:Button text="Click Build" display-tooltip-when-elided="true" name="Build" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,70 +0,0 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
internal class ScriptableBuildPipelineViewer : BuildPipelineViewerBase
{
public ScriptableBuildPipelineViewer(string packageName, BuildTarget buildTarget, VisualElement parent)
: base(packageName, EBuildPipeline.ScriptableBuildPipeline, buildTarget, parent)
{
}
/// <summary>
/// 执行构建
/// </summary>
protected override void ExecuteBuild()
{
var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
var clearBuildCache = AssetBundleBuilderSetting.GetPackageClearBuildCache(PackageName, BuildPipeline);
var useAssetDependencyDB = AssetBundleBuilderSetting.GetPackageUseAssetDependencyDB(PackageName, BuildPipeline);
var builtinShaderBundleName = GetBuiltinShaderBundleName();
ScriptableBuildParameters buildParameters = new ScriptableBuildParameters();
buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
buildParameters.BuildPipeline = BuildPipeline.ToString();
buildParameters.BuildBundleType = (int)EBuildBundleType.AssetBundle;
buildParameters.BuildTarget = BuildTarget;
buildParameters.PackageName = PackageName;
buildParameters.PackageVersion = GetPackageVersion();
buildParameters.EnableSharePackRule = true;
buildParameters.VerifyBuildingResult = true;
buildParameters.FileNameStyle = fileNameStyle;
buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
buildParameters.CompressOption = compressOption;
buildParameters.ClearBuildCacheFiles = clearBuildCache;
buildParameters.UseAssetDependencyDB = useAssetDependencyDB;
buildParameters.BuiltinShadersBundleName = builtinShaderBundleName;
buildParameters.EncryptionServices = CreateEncryptionInstance();
ScriptableBuildPipeline pipeline = new ScriptableBuildPipeline();
var buildResult = pipeline.Run(buildParameters, true);
if (buildResult.Success)
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
}
/// <summary>
/// 内置着色器资源包名称
/// 注意:和自动收集的着色器资源包名保持一致!
/// </summary>
private string GetBuiltinShaderBundleName()
{
var uniqueBundleName = AssetBundleCollectorSettingData.Setting.UniqueBundleName;
var packRuleResult = DefaultPackRule.CreateShadersPackRuleResult();
return packRuleResult.GetBundleName(PackageName, uniqueBundleName);
}
}
}
#endif

View File

@@ -265,7 +265,7 @@ namespace YooAsset.Editor
}
private static string GetRuleDisplayName(string name, Type type)
{
var attribute = DisplayNameAttributeHelper.GetAttribute<DisplayNameAttribute>(type);
var attribute = EditorTools.GetAttribute<DisplayNameAttribute>(type);
if (attribute != null && string.IsNullOrEmpty(attribute.DisplayName) == false)
return attribute.DisplayName;
else

View File

@@ -762,6 +762,7 @@ namespace YooAsset.Editor
elementTop.Add(objectField);
var label = objectField.Q<Label>();
label.style.minWidth = 63;
UIElementsTools.SetObjectFieldShowPath(objectField);
}
// Bottom VisualElement
@@ -851,8 +852,6 @@ namespace YooAsset.Editor
var collector = selectGroup.Collectors[index];
var collectObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(collector.CollectPath);
if (collectObject != null)
collectObject.name = collector.CollectPath;
// 注意:非主资源收集器的标签栏需要被冻结
var textTags = element.Q<TextField>("TextField1");
@@ -885,13 +884,13 @@ namespace YooAsset.Editor
{
collector.CollectPath = AssetDatabase.GetAssetPath(evt.newValue);
collector.CollectorGUID = AssetDatabase.AssetPathToGUID(collector.CollectPath);
objectField1.value.name = collector.CollectPath;
AssetBundleCollectorSettingData.ModifyCollector(selectGroup, collector);
if (foldout.value)
{
RefreshFoldout(foldout, selectGroup, collector);
}
});
UIElementsTools.RefreshObjectFieldShowPath(objectField1);
// Collector Type
var popupField0 = element.Q<PopupField<string>>("PopupField0");

View File

@@ -70,7 +70,11 @@ namespace YooAsset.Editor
foreach (var cacheInfoPair in _database)
{
var assetPath = cacheInfoPair.Key;
#if UNITY_2021_3_OR_NEWER
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath, AssetPathToGUIDOptions.OnlyExistingAssets);
#else
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath);
#endif
if (string.IsNullOrEmpty(assetGUID))
{
removeList.Add(assetPath);
@@ -182,17 +186,39 @@ namespace YooAsset.Editor
throw new Exception($"Fatal : can not found cache info : {assetPath}");
}
var result = new HashSet<string> { assetPath };
CollectDependencies(assetPath, result, recursive);
var result = new HashSet<string>();
// 递归收集依赖时,依赖列表中包含主资源
if (recursive)
{
result.Add(assetPath);
}
// 收集依赖
CollectDependencies(assetPath, assetPath, result, recursive);
// 注意AssetDatabase.GetDependencies保持一致将主资源添加到依赖列表最前面
return result.ToArray();
}
private void CollectDependencies(string assetPath, HashSet<string> result, bool recursive)
private void CollectDependencies(string parent, string assetPath, HashSet<string> result, bool recursive)
{
if (_database.TryGetValue(assetPath, out var cacheInfo) == false)
{
throw new Exception($"Fatal : can not found cache info : {assetPath}");
// 说明:检测是否为丢失引用的资产
#if UNITY_2021_3_OR_NEWER
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath, AssetPathToGUIDOptions.OnlyExistingAssets);
#else
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath);
#endif
if (string.IsNullOrEmpty(assetGUID))
{
Debug.LogWarning($"{parent} found missing asset : {assetPath}");
return;
}
else
{
throw new Exception($"Fatal : can not found cache info : {assetPath}");
}
}
foreach (var dependGUID in cacheInfo.DependGUIDs)
@@ -213,7 +239,7 @@ namespace YooAsset.Editor
// 递归收集依赖
if (recursive)
CollectDependencies(dependAssetPath, result, recursive);
CollectDependencies(assetPath, dependAssetPath, result, recursive);
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Reflection;
namespace YooAsset.Editor
{
@@ -15,22 +14,4 @@ namespace YooAsset.Editor
this.DisplayName = name;
}
}
public static class DisplayNameAttributeHelper
{
internal static T GetAttribute<T>(Type type) where T : Attribute
{
return (T)type.GetCustomAttribute(typeof(T), false);
}
internal static T GetAttribute<T>(MethodInfo methodInfo) where T : Attribute
{
return (T)methodInfo.GetCustomAttribute(typeof(T), false);
}
internal static T GetAttribute<T>(FieldInfo field) where T : Attribute
{
return (T)field.GetCustomAttribute(typeof(T), false);
}
}
}

View File

@@ -71,9 +71,10 @@ namespace YooAsset.Editor
public bool UseAssetDependencyDB;
public bool EnableSharePackRule;
public bool SingleReferencedPackAlone;
public string EncryptionClassName;
public string EncryptionServicesClassName;
public string ManifestServicesClassName;
public EFileNameStyle FileNameStyle;
// 引擎参数
public ECompressOption CompressOption;
public bool DisableWriteTypeTree;

View File

@@ -66,7 +66,8 @@ namespace YooAsset.Editor
BindListViewItem("Use Asset Dependency DB", $"{buildReport.Summary.UseAssetDependencyDB}");
BindListViewItem("Enable Share Pack Rule", $"{buildReport.Summary.EnableSharePackRule}");
BindListViewItem("Single Referenced Pack Alone", $"{buildReport.Summary.SingleReferencedPackAlone}");
BindListViewItem("Encryption Class Name", buildReport.Summary.EncryptionClassName);
BindListViewItem("Encryption Services", buildReport.Summary.EncryptionServicesClassName);
BindListViewItem("Manifest Services", buildReport.Summary.ManifestServicesClassName);
BindListViewItem("FileNameStyle", $"{buildReport.Summary.FileNameStyle}");
BindListViewItem("CompressOption", $"{buildReport.Summary.CompressOption}");
BindListViewItem("DisableWriteTypeTree", $"{buildReport.Summary.DisableWriteTypeTree}");

View File

@@ -129,6 +129,23 @@ namespace YooAsset.Editor
}
#endregion
#region Attribute
public static T GetAttribute<T>(Type type) where T : Attribute
{
return (T)type.GetCustomAttribute(typeof(T), false);
}
public static T GetAttribute<T>(MethodInfo methodInfo) where T : Attribute
{
return (T)methodInfo.GetCustomAttribute(typeof(T), false);
}
public static T GetAttribute<T>(FieldInfo field) where T : Attribute
{
return (T)field.GetCustomAttribute(typeof(T), false);
}
#endregion
#region PackageManager
public static string GetPackageManagerYooVersion()
{

View File

@@ -0,0 +1,42 @@
#if UNITY_2019_4_OR_NEWER
using UnityEditor;
using System;
namespace YooAsset.Editor
{
public class AssetObjectCell : ITableCell, IComparable
{
public string SearchTag { private set; get; }
public object CellValue { set; get; }
public string StringValue
{
get
{
return (string)CellValue;
}
}
public AssetObjectCell(string searchTag, string assetPath)
{
SearchTag = searchTag;
CellValue = assetPath;
}
public object GetDisplayObject()
{
return AssetDatabase.LoadMainAssetAtPath(StringValue);
}
public int CompareTo(object other)
{
if (other is AssetObjectCell cell)
{
return this.StringValue.CompareTo(cell.StringValue);
}
else
{
return 0;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39db4a569a0f69443a7675e19c99c389
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -31,9 +31,14 @@ namespace YooAsset.Editor
var cell = new ButtonCell(searchTag);
Cells.Add(cell);
}
public void AddAssetPathCell(string searchTag, string path)
public void AddAssetPathCell(string searchTag, string assetPath)
{
var cell = new AssetPathCell(searchTag, path);
var cell = new AssetPathCell(searchTag, assetPath);
Cells.Add(cell);
}
public void AddAssetObjectCell(string searchTag, string assetPath)
{
var cell = new AssetObjectCell(searchTag, assetPath);
Cells.Add(cell);
}
public void AddStringValueCell(string searchTag, string value)

View File

@@ -33,6 +33,67 @@ namespace YooAsset.Editor
}
}
/// <summary>
/// 设置元素显示文本为资源路径
/// </summary>
public static void SetObjectFieldShowPath(ObjectField objectField)
{
string LabelClassName = "unity-object-field-display__label";
var nameLable = objectField.Q<Label>(className: LabelClassName);
if (nameLable == null)
return;
objectField.RegisterValueChangedCallback(evt =>
{
Object obj = evt.newValue;
if (obj == null)
{
nameLable.text = "None (Object)";
return;
}
// 获取资源路径(仅适用于项目资源)
string path = AssetDatabase.GetAssetPath(obj);
if (string.IsNullOrEmpty(path) == false)
{
nameLable.text = path;
}
else
{
nameLable.text = obj.name;
}
});
}
/// <summary>
/// 刷新元素显示文本内容
/// </summary>
public static void RefreshObjectFieldShowPath(ObjectField objectField)
{
string LabelClassName = "unity-object-field-display__label";
var nameLable = objectField.Q<Label>(className: LabelClassName);
if (nameLable == null)
return;
Object obj = objectField.value;
if (obj == null)
{
nameLable.text = "None (Object)";
return;
}
// 获取资源路径(仅适用于项目资源)
string path = AssetDatabase.GetAssetPath(obj);
if (string.IsNullOrEmpty(path) == false)
{
nameLable.text = path;
}
else
{
nameLable.text = obj.name;
}
}
/// <summary>
/// 设置按钮图标
/// </summary>

View File

@@ -5,6 +5,7 @@
[assembly: InternalsVisibleTo("YooAsset.Test.Editor")]
// 外部友元
[assembly: InternalsVisibleTo("YooAsset.MiniGame")]
[assembly: InternalsVisibleTo("YooAsset.RuntimeExtension")]
[assembly: InternalsVisibleTo("YooAsset.EditorExtension")]
[assembly: InternalsVisibleTo("Assembly-CSharp-Editor")]

View File

@@ -69,6 +69,8 @@ namespace YooAsset
url = new System.Uri(path).ToString();
#elif UNITY_STANDALONE || UNITY_WSA
url = StringUtility.Format("file:///{0}", path);
#elif UNITY_TVOS
url = StringUtility.Format("file:///{0}", path);
#else
throw new System.NotImplementedException();
#endif

View File

@@ -106,7 +106,7 @@ namespace YooAsset
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
//注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalUpdate();
}
public override void UnSuspendLoad()

View File

@@ -112,7 +112,7 @@ namespace YooAsset
}
internal override void InternalWaitForAsyncComplete()
{
//TODO 场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
//注意:场景加载不支持异步转同步,为了支持同步加载方法需要实现该方法!
InternalUpdate();
}
public override void UnSuspendLoad()

View File

@@ -88,6 +88,11 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -174,6 +179,10 @@ namespace YooAsset
{
DecryptionServices = (IDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -11,7 +11,7 @@ namespace YooAsset
/// <summary>
/// 在构建应用程序前自动生成内置资源目录文件。
/// 原理搜索StreamingAssets目录下的所有资源文件然后将这些文件信息写入文件,并存储在Resources目录下
/// 原理搜索StreamingAssets目录下的所有资源文件将这些文件信息写入文件然后在运行时做查询用途
/// </summary>
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
@@ -21,7 +21,7 @@ namespace YooAsset
DirectoryInfo rootDirectory = new DirectoryInfo(rootPath);
if (rootDirectory.Exists == false)
{
UnityEngine.Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}");
Debug.LogWarning($"Can not found StreamingAssets root directory : {rootPath}");
return;
}
@@ -31,10 +31,17 @@ namespace YooAsset
{
string packageName = subDirectory.Name;
string pacakgeDirectory = subDirectory.FullName;
bool result = CreateBuildinCatalogFile(packageName, pacakgeDirectory);
if (result == false)
try
{
throw new System.Exception($"Create package {packageName} catalog file failed ! See the detail error in console !");
bool result = CreateBuildinCatalogFile(null, packageName, pacakgeDirectory);
if (result == false)
{
Debug.LogError($"Create package {packageName} catalog file failed ! See the detail error in console !");
}
}
catch (System.Exception ex)
{
Debug.LogError($"Create package {packageName} catalog file failed ! {ex.Message}");
}
}
}
@@ -42,7 +49,7 @@ namespace YooAsset
/// <summary>
/// 生成包裹的内置资源目录文件
/// </summary>
public static bool CreateBuildinCatalogFile(string packageName, string pacakgeDirectory)
public static bool CreateBuildinCatalogFile(IManifestServices services, string packageName, string pacakgeDirectory)
{
// 获取资源清单版本
string packageVersion;
@@ -70,7 +77,7 @@ namespace YooAsset
}
var binaryData = FileUtility.ReadAllBytes(manifestFilePath);
packageManifest = ManifestTools.DeserializeFromBinary(binaryData);
packageManifest = ManifestTools.DeserializeFromBinary(binaryData, services);
}
// 获取文件名映射关系

View File

@@ -106,10 +106,11 @@ namespace YooAsset
if (_loadCatalogFileOp == null)
{
#if UNITY_EDITOR
/*
// 兼容性初始化
// 说明:内置文件系统在编辑器下运行时需要动态生成
string packageRoot = _fileSystem.FileRoot;
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.ManifestServices, _fileSystem.PackageName, packageRoot);
if (result == false)
{
_steps = ESteps.Done;
@@ -117,6 +118,7 @@ namespace YooAsset
Error = $"Create package catalog file failed ! See the detail error in console !";
return;
}
*/
#endif
_loadCatalogFileOp = new LoadBuildinCatalogFileOperation(_fileSystem);

View File

@@ -85,7 +85,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -58,7 +58,7 @@ namespace YooAsset
/// <summary>
/// 自定义参数:远程服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:初始化的时候缓存文件校验级别
@@ -99,6 +99,11 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -221,6 +226,10 @@ namespace YooAsset
{
DecryptionServices = (IDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");
@@ -559,6 +568,21 @@ namespace YooAsset
};
return DecryptionServices.LoadAssetBundleAsync(fileInfo);
}
/// <summary>
/// 加载加密资源文件
/// </summary>
public DecryptResult LoadEncryptedAssetBundleFallback(PackageBundle bundle)
{
string filePath = GetCacheBundleFileLoadPath(bundle);
var fileInfo = new DecryptFileInfo()
{
BundleName = bundle.BundleName,
FileLoadCRC = bundle.UnityCRC,
FileLoadPath = filePath,
};
return DecryptionServices.LoadAssetBundleFallback(fileInfo);
}
#endregion
}
}

View File

@@ -164,11 +164,23 @@ namespace YooAsset
{
if (_bundle.Encrypted)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
return;
var decryptResult = _fileSystem.LoadEncryptedAssetBundleFallback(_bundle);
_assetBundle = decryptResult.Result;
if (_assetBundle != null)
{
_steps = ESteps.Done;
Result = new AssetBundleResult(_fileSystem, _bundle, _assetBundle, _managedStream);
Status = EOperationStatus.Succeed;
return;
}
else
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Failed to load encrypted asset bundle file : {_bundle.BundleName}";
YooLogger.Error(Error);
return;
}
}
// 注意:在安卓移动平台,华为和三星真机上有极小概率加载资源包失败。
@@ -216,6 +228,7 @@ namespace YooAsset
{
if (ExecuteWhileDone())
{
//TODO 拷贝本地文件失败也会触发该错误!
if (_downloadFileOp != null && _downloadFileOp.Status == EOperationStatus.Failed)
YooLogger.Error($"Try load bundle {_bundle.BundleName} from remote !");

View File

@@ -168,12 +168,15 @@ namespace YooAsset
{
while (true)
{
//TODO 如果是导入或解压本地文件,执行等待完毕
//TODO 如果是导入或解压本地文件,执行等待完毕,该操作会挂起主线程!
if (_isReuqestLocalFile)
{
InternalUpdate();
if (IsDone)
break;
// 短暂休眠避免完全卡死
System.Threading.Thread.Sleep(1);
}
else
{

View File

@@ -187,12 +187,15 @@ namespace YooAsset
{
while (true)
{
//TODO 如果是导入或解压本地文件,执行等待完毕
//TODO 如果是导入或解压本地文件,执行等待完毕,该操作会挂起主线程!
if (_isReuqestLocalFile)
{
InternalUpdate();
if (IsDone)
break;
// 短暂休眠避免完全卡死
System.Threading.Thread.Sleep(1);
}
else
{

View File

@@ -75,7 +75,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileData);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _fileData);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -71,10 +71,13 @@ namespace YooAsset
{
while (true)
{
//TODO 等待子线程验证文件完毕,该操作会挂起主线程
//TODO 等待子线程验证文件完毕,该操作会挂起主线程
InternalUpdate();
if (IsDone)
break;
// 短暂休眠避免完全卡死
System.Threading.Thread.Sleep(1);
}
}

View File

@@ -75,7 +75,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_fileData);
_deserializer = new DeserializeManifestOperation(null, _fileData);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -3,11 +3,6 @@ namespace YooAsset
{
internal class DefaultUnpackFileSystemDefine
{
/// <summary>
/// 文件系统的优先级
/// </summary>
public const int DefaultPriority = 11;
/// <summary>
/// 保存的资源文件的文件夹名称
/// </summary>

View File

@@ -46,12 +46,17 @@ namespace YooAsset
/// <summary>
/// 自定义参数:跨域下载服务接口
/// </summary>
public IRemoteServices RemoteServices { private set; get; } = null;
public IRemoteServices RemoteServices { private set; get; }
/// <summary>
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -111,6 +116,10 @@ namespace YooAsset
{
DecryptionServices = (IWebDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -88,7 +88,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -61,6 +61,11 @@ namespace YooAsset
/// 自定义参数:解密方法类
/// </summary>
public IWebDecryptionServices DecryptionServices { private set; get; }
/// <summary>
/// 自定义参数:资源清单服务类
/// </summary>
public IManifestServices ManifestServices { private set; get; }
#endregion
@@ -116,6 +121,10 @@ namespace YooAsset
{
DecryptionServices = (IWebDecryptionServices)value;
}
else if (name == FileSystemParametersDefine.MANIFEST_SERVICES)
{
ManifestServices = (IManifestServices)value;
}
else
{
YooLogger.Warning($"Invalid parameter : {name}");

View File

@@ -33,10 +33,11 @@ namespace YooAsset
if (_loadCatalogFileOp == null)
{
#if UNITY_EDITOR
/*
// 兼容性初始化
// 说明:内置文件系统在编辑器下运行时需要动态生成
string packageRoot = _fileSystem.FileRoot;
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.PackageName, packageRoot);
bool result = DefaultBuildinFileSystemBuild.CreateBuildinCatalogFile(_fileSystem.ManifestServices, _fileSystem.PackageName, packageRoot);
if (result == false)
{
_steps = ESteps.Done;
@@ -44,6 +45,7 @@ namespace YooAsset
Error = $"Create package catalog file failed ! See the detail error in console !";
return;
}
*/
#endif
_loadCatalogFileOp = new LoadWebServerCatalogFileOperation(_fileSystem);

View File

@@ -85,7 +85,7 @@ namespace YooAsset
{
if (_deserializer == null)
{
_deserializer = new DeserializeManifestOperation(_webDataRequestOp.Result);
_deserializer = new DeserializeManifestOperation(_fileSystem.ManifestServices, _webDataRequestOp.Result);
_deserializer.StartOperation();
AddChildOperation(_deserializer);
}

View File

@@ -7,6 +7,7 @@ namespace YooAsset
public const string INSTALL_CLEAR_MODE = "INSTALL_CLEAR_MODE";
public const string REMOTE_SERVICES = "REMOTE_SERVICES";
public const string DECRYPTION_SERVICES = "DECRYPTION_SERVICES";
public const string MANIFEST_SERVICES = "MANIFEST_SERVICES";
public const string APPEND_FILE_EXTENSION = "APPEND_FILE_EXTENSION";
public const string DISABLE_CATALOG_FILE = "DISABLE_CATALOG_FILE";
public const string DISABLE_UNITY_WEB_CACHE = "DISABLE_UNITY_WEB_CACHE";

View File

@@ -42,6 +42,11 @@ namespace YooAsset
/// 同时加载Bundle文件的最大并发数
/// </summary>
public int BundleLoadingMaxConcurrency = int.MaxValue;
/// <summary>
/// WebGL平台强制同步加载资源对象
/// </summary>
public bool WebGLForceSyncLoadAsset = false;
}
/// <summary>

View File

@@ -260,8 +260,11 @@ namespace YooAsset
StartOperation();
}
IsWaitForAsyncComplete = true;
InternalWaitForAsyncComplete();
if (IsWaitForAsyncComplete == false)
{
IsWaitForAsyncComplete = true;
InternalWaitForAsyncComplete();
}
}
#region

View File

@@ -14,7 +14,7 @@ namespace YooAsset
Done,
}
private readonly ResourceManager _resourceManager;
private readonly ResourceManager _resManager;
private readonly List<ProviderOperation> _providers = new List<ProviderOperation>(100);
private readonly List<ProviderOperation> _removeList = new List<ProviderOperation>(100);
private FSLoadBundleOperation _loadBundleOp;
@@ -53,7 +53,7 @@ namespace YooAsset
internal LoadBundleFileOperation(ResourceManager resourceManager, BundleInfo bundleInfo)
{
_resourceManager = resourceManager;
_resManager = resourceManager;
LoadBundleInfo = bundleInfo;
}
internal override void InternalStart()
@@ -73,7 +73,7 @@ namespace YooAsset
}
else
{
if (_resourceManager.BundleLoadingIsBusy())
if (_resManager.BundleLoadingIsBusy())
return;
_steps = ESteps.LoadBundleFile;
}
@@ -83,7 +83,7 @@ namespace YooAsset
{
if (_loadBundleOp == null)
{
_resourceManager.BundleLoadingCounter++;
_resManager.BundleLoadingCounter++;
_loadBundleOp = LoadBundleInfo.LoadBundleFile();
_loadBundleOp.StartOperation();
AddChildOperation(_loadBundleOp);
@@ -121,7 +121,7 @@ namespace YooAsset
}
// 统计计数减少
_resourceManager.BundleLoadingCounter--;
_resManager.BundleLoadingCounter--;
}
}
internal override void InternalWaitForAsyncComplete()
@@ -191,7 +191,7 @@ namespace YooAsset
{
foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs)
{
if (_resourceManager.CheckBundleDestroyed(bundleID) == false)
if (_resManager.CheckBundleDestroyed(bundleID) == false)
return false;
}
}
@@ -233,7 +233,7 @@ namespace YooAsset
// 移除资源提供者
if (_removeList.Count > 0)
{
_resourceManager.RemoveBundleProviders(_removeList);
_resManager.RemoveBundleProviders(_removeList);
_removeList.Clear();
}
}

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadAllAssetsOp = BundleResultObject.LoadAllAssetsAsync(MainAssetInfo);
_loadAllAssetsOp.StartOperation();
AddChildOperation(_loadAllAssetsOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadAllAssetsOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadAssetOp = BundleResultObject.LoadAssetAsync(MainAssetInfo);
_loadAssetOp.StartOperation();
AddChildOperation(_loadAssetOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadAssetOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -68,13 +68,14 @@ namespace YooAsset
private ESteps _steps = ESteps.None;
protected readonly ResourceManager _resManager;
private readonly LoadBundleFileOperation _mainBundleLoader;
private readonly List<LoadBundleFileOperation> _bundleLoaders = new List<LoadBundleFileOperation>(10);
private readonly HashSet<HandleBase> _handles = new HashSet<HandleBase>();
public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo)
{
_resManager = manager;
ProviderGUID = providerGUID;
MainAssetInfo = assetInfo;

View File

@@ -15,6 +15,11 @@ namespace YooAsset
_loadSubAssetsOp = BundleResultObject.LoadSubAssetsAsync(MainAssetInfo);
_loadSubAssetsOp.StartOperation();
AddChildOperation(_loadSubAssetsOp);
#if UNITY_WEBGL
if (_resManager.WebGLForceSyncLoadAsset())
_loadSubAssetsOp.WaitForAsyncComplete();
#endif
}
if (IsWaitForAsyncComplete)

View File

@@ -15,6 +15,7 @@ namespace YooAsset
private long _sceneCreateIndex = 0;
private IBundleQuery _bundleQuery;
private int _bundleLoadingMaxConcurrency;
private bool _webGLForceSyncLoadAsset;
/// <summary>
/// 所属包裹
@@ -43,6 +44,7 @@ namespace YooAsset
public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices)
{
_bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency;
_webGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset;
_bundleQuery = bundleServices;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
@@ -321,6 +323,10 @@ namespace YooAsset
{
return BundleLoadingCounter >= _bundleLoadingMaxConcurrency;
}
internal bool WebGLForceSyncLoadAsset()
{
return _webGLForceSyncLoadAsset;
}
private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo)
{

View File

@@ -44,7 +44,7 @@ namespace YooAsset
/// <summary>
/// 序列化(二进制文件)
/// </summary>
public static void SerializeToBinary(string savePath, PackageManifest manifest)
public static void SerializeToBinary(string savePath, PackageManifest manifest, IManifestServices services)
{
using (FileStream fs = new FileStream(savePath, FileMode.Create))
{
@@ -96,9 +96,20 @@ namespace YooAsset
buffer.WriteInt32Array(packageBundle.DependBundleIDs);
}
// 写入文件流
buffer.WriteToStream(fs);
fs.Flush();
// 清单处理操作
if (services != null)
{
var tempBytes = buffer.GetBytes();
var resultBytes = services.ProcessManifest(tempBytes);
fs.Write(resultBytes, 0, resultBytes.Length);
fs.Flush();
}
else
{
// 写入文件流
buffer.WriteToStream(fs);
fs.Flush();
}
}
}
@@ -113,10 +124,19 @@ namespace YooAsset
/// <summary>
/// 反序列化(二进制文件)
/// </summary>
public static PackageManifest DeserializeFromBinary(byte[] binaryData)
public static PackageManifest DeserializeFromBinary(byte[] binaryData, IManifestServices services)
{
// 创建缓存器
BufferReader buffer = new BufferReader(binaryData);
BufferReader buffer;
if (services != null)
{
var resultBytes = services.RestoreManifest(binaryData);
buffer = new BufferReader(resultBytes);
}
else
{
buffer = new BufferReader(binaryData);
}
// 读取文件标记
uint fileSign = buffer.ReadUInt32();

View File

@@ -10,6 +10,7 @@ namespace YooAsset
private enum ESteps
{
None,
RestoreFileData,
DeserializeFileHeader,
PrepareAssetList,
DeserializeAssetList,
@@ -19,7 +20,9 @@ namespace YooAsset
Done,
}
private readonly BufferReader _buffer;
private readonly IManifestServices _services;
private byte[] _sourceData;
private BufferReader _buffer;
private int _packageAssetCount;
private int _packageBundleCount;
private int _progressTotalValue;
@@ -30,13 +33,14 @@ namespace YooAsset
/// </summary>
public PackageManifest Manifest { private set; get; }
public DeserializeManifestOperation(byte[] binaryData)
public DeserializeManifestOperation(IManifestServices services, byte[] binaryData)
{
_buffer = new BufferReader(binaryData);
_services = services;
_sourceData = binaryData;
}
internal override void InternalStart()
{
_steps = ESteps.DeserializeFileHeader;
_steps = ESteps.RestoreFileData;
}
internal override void InternalUpdate()
{
@@ -45,6 +49,19 @@ namespace YooAsset
try
{
if (_steps == ESteps.RestoreFileData)
{
if (_services != null)
{
var resultData = _services.RestoreManifest(_sourceData);
if (resultData != null)
_sourceData = resultData;
}
_buffer = new BufferReader(_sourceData);
_steps = ESteps.DeserializeFileHeader;
}
if (_steps == ESteps.DeserializeFileHeader)
{
if (_buffer.IsValid == false)

View File

@@ -42,15 +42,23 @@ namespace YooAsset
public interface IDecryptionServices
{
/// <summary>
/// 同步方式获取解密的资源包对象
/// 同步方式获取解密的资源包
/// </summary>
DecryptResult LoadAssetBundle(DecryptFileInfo fileInfo);
/// <summary>
/// 异步方式获取解密的资源包对象
/// 异步方式获取解密的资源包
/// </summary>
DecryptResult LoadAssetBundleAsync(DecryptFileInfo fileInfo);
/// <summary>
/// 后备方式获取解密的资源包
/// 注意:当正常解密方法失败后,会触发后备加载!
/// 说明建议通过LoadFromMemory()方法加载资源包作为保底机制。
/// issues : https://github.com/tuyoogame/YooAsset/issues/562
/// </summary>
DecryptResult LoadAssetBundleFallback(DecryptFileInfo fileInfo);
/// <summary>
/// 获取解密的字节数据
/// </summary>

View File

@@ -1,6 +1,18 @@

namespace YooAsset
{
public struct EncryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 文件路径
/// </summary>
public string FileLoadPath;
}
public struct EncryptResult
{
/// <summary>
@@ -14,19 +26,6 @@ namespace YooAsset
public byte[] EncryptedData;
}
public struct EncryptFileInfo
{
/// <summary>
/// 资源包名称
/// </summary>
public string BundleName;
/// <summary>
/// 文件路径
/// </summary>
public string FileLoadPath;
}
public interface IEncryptionServices
{
EncryptResult Encrypt(EncryptFileInfo fileInfo);

View File

@@ -0,0 +1,19 @@

namespace YooAsset
{
/// <summary>
/// 资源清单文件处理服务接口
/// </summary>
public interface IManifestServices
{
/// <summary>
/// 处理资源清单(压缩和加密)
/// </summary>
byte[] ProcessManifest(byte[] fileData);
/// <summary>
/// 还原资源清单(解压和解密)
/// </summary>
byte[] RestoreManifest(byte[] fileData);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7378f37c14fe59b4dbb5c1259a3f19c8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -36,6 +36,16 @@ namespace YooAsset
_index = 0;
}
/// <summary>
/// 获取有效数据
/// </summary>
public byte[] GetBytes()
{
byte[] newArray = new byte[_index];
Buffer.BlockCopy(_buffer, 0, newArray, 0, _index);
return newArray;
}
/// <summary>
/// 将有效数据写入文件流
/// </summary>

View File

@@ -34,6 +34,20 @@ namespace YooAsset
return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test"
}
/// <summary>
/// URL地址是否包含双斜杠
/// 注意:只检查协议之后的部分
/// </summary>
public static bool HasDoubleSlashes(string url)
{
if (url == null)
throw new ArgumentNullException();
int protocolIndex = url.IndexOf("://");
string partToCheck = protocolIndex == -1 ? url : url.Substring(protocolIndex + 3);
return partToCheck.Contains("//") || partToCheck.Contains(@"\\");
}
/// <summary>
/// 合并路径
/// </summary>

View File

@@ -75,7 +75,14 @@ namespace YooAsset
if (_driver != null)
GameObject.Destroy(_driver);
OnApplicationQuit(true);
// 终止并清空所有包裹的异步操作
ClearAllPackageOperation();
// 卸载所有AssetBundle
AssetBundle.UnloadAllAssetBundles(true);
// 清空资源包裹列表
_packages.Clear();
}
}
@@ -91,25 +98,15 @@ namespace YooAsset
}
/// <summary>
/// 应用程序退出处理
/// 终止并清空所有包裹的异步操作
/// </summary>
internal static void OnApplicationQuit(bool unloadAllAssetBundles)
internal static void ClearAllPackageOperation()
{
// 说明在编辑器下确保播放被停止时IO类操作被终止。
foreach (var package in _packages)
{
OperationSystem.ClearPackageOperation(package.PackageName);
}
OperationSystem.DestroyAll();
// 清空资源包裹列表
_packages.Clear();
// 卸载所有AssetBundle
if (unloadAllAssetBundles)
{
AssetBundle.UnloadAllAssetBundles(true);
}
}
/// <summary>

View File

@@ -24,7 +24,8 @@ namespace YooAsset
#if UNITY_EDITOR
void OnApplicationQuit()
{
YooAssets.OnApplicationQuit(false);
// 说明在编辑器下确保播放被停止时IO类操作被终止。
YooAssets.ClearAllPackageOperation();
}
#endif

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b1774501eb8484d47b6c9d61585b4cd4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
internal class ClearBuildCacheWindow
{
[MenuItem("Tools/Clear Build Cache", false, 2)]
public static void OpenWindow()
{
// 清空SBP构建缓存
UnityEditor.Build.Pipeline.Utilities.BuildCache.PurgeCache(false);
// 删除AssetDependDB文件
string projectPath = YooAsset.Editor.EditorTools.GetProjectPath();
string databaseFilePath = $"{projectPath}/Library/AssetDependencyDB";
if (File.Exists(databaseFilePath))
{
File.Delete(databaseFilePath);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8bf2d0ddd780f1746b7f1c7e0f9959e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -106,11 +106,11 @@ namespace YooAsset.Editor
// 加载补丁清单1
byte[] bytesData1 = FileUtility.ReadAllBytes(_manifestPath1);
PackageManifest manifest1 = ManifestTools.DeserializeFromBinary(bytesData1);
PackageManifest manifest1 = ManifestTools.DeserializeFromBinary(bytesData1, null); //TODO 自行处理解密
// 加载补丁清单1
byte[] bytesData2 = FileUtility.ReadAllBytes(_manifestPath2);
PackageManifest manifest2 = ManifestTools.DeserializeFromBinary(bytesData2);
PackageManifest manifest2 = ManifestTools.DeserializeFromBinary(bytesData2, null); //TODO 自行处理解密
// 拷贝文件列表
foreach (var bundle2 in manifest2.BundleList)

View File

@@ -71,7 +71,7 @@ namespace YooAsset.Editor
// 加载补丁清单
byte[] bytesData = FileUtility.ReadAllBytes(manifestFilePath);
PackageManifest manifest = ManifestTools.DeserializeFromBinary(bytesData);
PackageManifest manifest = ManifestTools.DeserializeFromBinary(bytesData, null); //TODO 自行处理解密
// 拷贝文件列表
int fileCount = 0;

Some files were not shown because too many files have changed in this diff Show More