Compare commits

...

25 Commits

Author SHA1 Message Date
何冠峰
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
何冠峰
eabebf3d8f Update CHANGELOG.md 2025-05-13 10:47:59 +08:00
何冠峰
4ef789520a Update package.json 2025-05-13 10:47:49 +08:00
何冠峰
4322f3c58c fix #545 2025-05-13 10:23:22 +08:00
何冠峰
c40a796170 fix #542 2025-05-13 10:11:06 +08:00
何冠峰
32841d4773 Update AssetBundleDebuggerWindow.cs 2025-05-09 15:29:26 +08:00
何冠峰
e469b32d94 refactor: The tag diffusion logic in the collector
优化收集器tag传染扩散逻辑,避免Group里配置了Tag导致的无意义的警告信息。
2025-04-23 18:42:26 +08:00
何冠峰
c0e5315953 feat : Buld the pipeline output the log file.
构建管线输出构建日志到输出目录下。
2025-04-23 18:19:13 +08:00
何冠峰
7b5f366533 Build system add BuiltinShadersBundleNameIsNull ErrorCode 2025-04-23 16:56:03 +08:00
何冠峰
e674d5bf97 update extension sample
PanelMonitor增加控制开关
2025-04-23 16:39:07 +08:00
何冠峰
9b0bebd981 refactor : Macro scripts control by YOO_ASSET_EXPERIMENT 2025-04-23 16:38:17 +08:00
何冠峰
dc46462bfa fix : remove Caching class
it's not support in webGL
2025-04-23 14:14:34 +08:00
何冠峰
51c9943cf2 修复了输出csproject工程文件编码为UTF16的问题
修正BOM问题
2025-04-22 17:41:36 +08:00
何冠峰
3db9b750e3 update logo 2025-04-22 16:47:44 +08:00
何冠峰
1b57a0b7df 修复了输出csproject工程文件编码为UTF16的问题。 2025-04-22 16:47:33 +08:00
何冠峰
bd5ce1e6bd perf : webgl platform use crc verify the bundle when first time downloaded
WebGL平台首次下载会验证CRC。
2025-04-18 18:21:24 +08:00
何冠峰
7eb74d4dd1 update extension sample 2025-04-18 17:11:40 +08:00
何冠峰
a384ca1f18 feat : scriptable build pipeline add StripUnityVersion parameter.
新增构建参数
2025-04-18 16:48:03 +08:00
89 changed files with 413 additions and 51 deletions

View File

@@ -2,6 +2,46 @@
All notable changes to this package will be documented in this file. All notable changes to this package will be documented in this file.
## [2.3.9] - 2025-05-13
### Improvements
- 增加了YOO_ASSET_EXPERIMENT宏用于控制实验性代码的开关。
- 构建管线目前会输出构建日志到输出目录下,方便查看引擎在构建时主动清空的控制台日志。
- 优化了收集器tag传染扩散逻辑避免Group里配置了Tag导致的无意义的警告信息。
- 扩展工程内PanelMonitor代码默认关闭状态。
### Fixed
- (#528) 修复了AssetDependencyDatabase在查询引擎资源对象是否存在的时效问题。
### Added
- (#542) 新增了资源管理系统销毁方法。
该方法会销毁所有的资源包裹和异步操作任务以及卸载所有AssetBundle对象
```csharp
public class YooAssets
{
/// <summary>
/// 销毁资源系统
/// </summary>
public static void Destroy();
}
```
- 新增了SBP构建管线的构建参数
```csharp
/// <summary>
/// 从AssetBundle文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
```
- 新增了构建错误码BuiltinShadersBundleNameIsNull
## [2.3.8] - 2025-04-17 ## [2.3.8] - 2025-04-17
### Improvements ### Improvements

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
#if YOO_ASSET_EXPERIMENT
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
public class MacroDefine public class MacroDefine
@@ -15,3 +16,4 @@ namespace YooAsset.Editor
}; };
} }
} }
#endif

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Xml; using System.Xml;
using UnityEditor; using UnityEditor;
#if YOO_ASSET_EXPERIMENT
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
[InitializeOnLoad] [InitializeOnLoad]
@@ -22,13 +23,21 @@ namespace YooAsset.Editor
return content; return content;
// 将修改后的XML结构重新输出为文本 // 将修改后的XML结构重新输出为文本
var stringWriter = new StringWriter(); using (var memoryStream = new MemoryStream())
var writerSettings = new XmlWriterSettings(); {
writerSettings.Indent = true; var writerSettings = new XmlWriterSettings
var xmlWriter = XmlWriter.Create(stringWriter, writerSettings); {
xmlDoc.WriteTo(xmlWriter); Indent = true,
xmlWriter.Flush(); Encoding = new UTF8Encoding(false), //无BOM
return stringWriter.ToString(); OmitXmlDeclaration = false
};
using (var xmlWriter = XmlWriter.Create(memoryStream, writerSettings))
{
xmlDoc.Save(xmlWriter);
}
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
} }
/// <summary> /// <summary>
@@ -94,3 +103,4 @@ namespace YooAsset.Editor
} }
} }
} }
#endif

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() private void ImportSingleBtn_clicked()
{ {
string selectFilePath = EditorUtility.OpenFilePanel("导入报告", _lastestOpenFolder, "json"); string selectFilePath = EditorUtility.OpenFilePanel("导入报告", _lastestOpenFolder, "json");
@@ -446,15 +472,31 @@ namespace YooAsset.Editor
var column = new TableColumn(header.HeaderTitle, header.HeaderTitle, columnStyle); var column = new TableColumn(header.HeaderTitle, header.HeaderTitle, columnStyle);
column.MakeCell = () => column.MakeCell = () =>
{ {
var label = new Label(); if (header.HeaderType == EHeaderType.AssetObject)
label.style.marginLeft = 3f; {
label.style.unityTextAlign = TextAnchor.MiddleLeft; var objectFiled = new ObjectField();
return label; 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) => column.BindCell = (VisualElement element, ITableData data, ITableCell cell) =>
{ {
var infoLabel = element as Label; if (header.HeaderType == EHeaderType.AssetObject)
infoLabel.text = (string)cell.GetDisplayObject(); {
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); _elementTableView.AddColumn(column);
} }
@@ -480,6 +522,10 @@ namespace YooAsset.Editor
{ {
tableData.AddAssetPathCell(scanInfo.HeaderTitle, scanInfo.ScanInfo); tableData.AddAssetPathCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
} }
else if (header.HeaderType == EHeaderType.AssetObject)
{
tableData.AddAssetObjectCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);
}
else if (header.HeaderType == EHeaderType.StringValue) else if (header.HeaderType == EHeaderType.StringValue)
{ {
tableData.AddStringValueCell(scanInfo.HeaderTitle, scanInfo.ScanInfo); tableData.AddStringValueCell(scanInfo.HeaderTitle, scanInfo.ScanInfo);

View File

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

View File

@@ -126,6 +126,12 @@ namespace YooAsset.Editor
if (string.IsNullOrEmpty(guid)) if (string.IsNullOrEmpty(guid))
throw new Exception($"{HeaderTitle} value is invalid asset path : {value}"); 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) else if (HeaderType == EHeaderType.DoubleValue)
{ {
if (double.TryParse(value, out double doubleValue) == false) if (double.TryParse(value, out double doubleValue) == false)

View File

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

View File

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

View File

@@ -32,8 +32,9 @@ namespace YooAsset.Editor
var buildParametersContext = new BuildParametersContext(buildParameters); var buildParametersContext = new BuildParametersContext(buildParameters);
_buildContext.SetContextObject(buildParametersContext); _buildContext.SetContextObject(buildParametersContext);
// 初始化日志 // 初始化日志系统
BuildLogger.InitLogger(enableLog); string logFilePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/buildInfo.log";
BuildLogger.InitLogger(enableLog, logFilePath);
// 执行构建流程 // 执行构建流程
BuildLogger.Log($"Begin to build package : {buildParameters.PackageName} by {buildParameters.BuildPipeline}"); BuildLogger.Log($"Begin to build package : {buildParameters.PackageName} by {buildParameters.BuildPipeline}");
@@ -50,6 +51,9 @@ namespace YooAsset.Editor
BuildLogger.Error(buildResult.ErrorInfo); BuildLogger.Error(buildResult.ErrorInfo);
} }
// 关闭日志系统
BuildLogger.Shuntdown();
return buildResult; return buildResult;
} }
} }

View File

@@ -11,7 +11,7 @@ namespace YooAsset.Editor
void IBuildTask.Run(BuildContext context) void IBuildTask.Run(BuildContext context)
{ {
var buildParametersContext = context.GetContextObject<BuildParametersContext>(); var buildParametersContext = context.GetContextObject<BuildParametersContext>();
var buildParameters = buildParametersContext.Parameters; var buildParameters = buildParametersContext.Parameters as ScriptableBuildParameters;
// 检测基础构建参数 // 检测基础构建参数
buildParametersContext.CheckBuildParameters(); buildParametersContext.CheckBuildParameters();
@@ -50,6 +50,13 @@ namespace YooAsset.Editor
{ {
BuildLogger.Log($"Create pipeline output directory: {pipelineOutputDirectory}"); BuildLogger.Log($"Create pipeline output directory: {pipelineOutputDirectory}");
} }
// 检测内置着色器资源包名称
if (string.IsNullOrEmpty(buildParameters.BuiltinShadersBundleName))
{
string warning = BuildLogger.GetErrorMessage(ErrorCode.BuiltinShadersBundleNameIsNull, $"Builtin shaders bundle name is null. It will cause resource redundancy !");
BuildLogger.Warning(warning);
}
} }
} }
} }

View File

@@ -14,6 +14,11 @@ namespace YooAsset.Editor
/// </summary> /// </summary>
public ECompressOption CompressOption = ECompressOption.Uncompressed; public ECompressOption CompressOption = ECompressOption.Uncompressed;
/// <summary>
/// 从AssetBundle文件头里剥离Unity版本信息
/// </summary>
public bool StripUnityVersion = false;
/// <summary> /// <summary>
/// 禁止写入类型树结构(可以降低包体和内存并提高加载效率) /// 禁止写入类型树结构(可以降低包体和内存并提高加载效率)
/// </summary> /// </summary>
@@ -70,6 +75,9 @@ namespace YooAsset.Editor
else else
throw new System.NotImplementedException(CompressOption.ToString()); throw new System.NotImplementedException(CompressOption.ToString());
if (StripUnityVersion)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.StripUnityVersion;
if (DisableWriteTypeTree) if (DisableWriteTypeTree)
buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree; buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;

View File

@@ -2,37 +2,100 @@
using System.IO; using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System.Text;
namespace YooAsset.Editor namespace YooAsset.Editor
{ {
internal static class BuildLogger internal static class BuildLogger
{ {
private static bool _enableLog = true; private const int MAX_LOG_BUFFER_SIZE = 1024 * 1024 * 2; //2MB
public static void InitLogger(bool enableLog) private static bool _enableLog = true;
private static string _logFilePath;
private static readonly object _lockObj = new object();
private static readonly StringBuilder _logBuilder = new StringBuilder(MAX_LOG_BUFFER_SIZE);
/// <summary>
/// 初始化日志系统
/// </summary>
public static void InitLogger(bool enableLog, string logFilePath)
{ {
_enableLog = enableLog; _enableLog = enableLog;
_logFilePath = logFilePath;
_logBuilder.Clear();
if (_enableLog)
{
if (string.IsNullOrEmpty(_logFilePath))
throw new Exception("Log file path is null or empty !");
Debug.Log($"Logger initialized at {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
}
}
/// <summary>
/// 关闭日志系统
/// </summary>
public static void Shuntdown()
{
if (_enableLog)
{
lock (_lockObj)
{
try
{
if (File.Exists(_logFilePath))
File.Delete(_logFilePath);
FileUtility.CreateFileDirectory(_logFilePath);
File.WriteAllText(_logFilePath, _logBuilder.ToString(), Encoding.UTF8);
_logBuilder.Clear();
}
catch (Exception ex)
{
Debug.LogError($"Failed to write log file: {ex.Message}");
}
}
}
} }
public static void Log(string message) public static void Log(string message)
{ {
if (_enableLog) if (_enableLog)
{ {
WriteLog("INFO", message);
Debug.Log(message); Debug.Log(message);
} }
} }
public static void Warning(string message) public static void Warning(string message)
{ {
Debug.LogWarning(message); if (_enableLog)
{
WriteLog("WARN", message);
Debug.LogWarning(message);
}
} }
public static void Error(string message) public static void Error(string message)
{ {
Debug.LogError(message); if (_enableLog)
{
WriteLog("ERROR", message);
Debug.LogError(message);
}
} }
public static string GetErrorMessage(ErrorCode code, string message) public static string GetErrorMessage(ErrorCode code, string message)
{ {
return $"[ErrorCode{(int)code}] {message}"; return $"[ErrorCode{(int)code}] {message}";
} }
private static void WriteLog(string level, string message)
{
lock (_lockObj)
{
string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level}] {message}";
_logBuilder.AppendLine(logEntry);
}
}
} }
} }

View File

@@ -15,6 +15,7 @@ namespace YooAsset.Editor
BuildPipelineIsNullOrEmpty = 116, BuildPipelineIsNullOrEmpty = 116,
BuildBundleTypeIsUnknown = 117, BuildBundleTypeIsUnknown = 117,
RecommendScriptBuildPipeline = 130, RecommendScriptBuildPipeline = 130,
BuiltinShadersBundleNameIsNull = 131,
// TaskGetBuildMap // TaskGetBuildMap
RemoveInvalidTags = 200, RemoveInvalidTags = 200,

View File

@@ -259,10 +259,13 @@ namespace YooAsset.Editor
} }
private List<string> GetAssetTags(AssetBundleCollectorGroup group) private List<string> GetAssetTags(AssetBundleCollectorGroup group)
{ {
List<string> tags = EditorTools.StringToStringList(group.AssetTags, ';'); List<string> result = EditorTools.StringToStringList(AssetTags, ';');
List<string> temper = EditorTools.StringToStringList(AssetTags, ';'); if (CollectorType == ECollectorType.MainAssetCollector)
tags.AddRange(temper); {
return tags; List<string> temps = EditorTools.StringToStringList(group.AssetTags, ';');
result.AddRange(temps);
}
return result;
} }
private List<AssetInfo> GetAllDependencies(CollectCommand command, string mainAssetPath) private List<AssetInfo> GetAllDependencies(CollectCommand command, string mainAssetPath)
{ {

View File

@@ -70,7 +70,11 @@ namespace YooAsset.Editor
foreach (var cacheInfoPair in _database) foreach (var cacheInfoPair in _database)
{ {
var assetPath = cacheInfoPair.Key; var assetPath = cacheInfoPair.Key;
#if UNITY_2021_3_OR_NEWER
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath, AssetPathToGUIDOptions.OnlyExistingAssets);
#else
var assetGUID = AssetDatabase.AssetPathToGUID(assetPath); var assetGUID = AssetDatabase.AssetPathToGUID(assetPath);
#endif
if (string.IsNullOrEmpty(assetGUID)) if (string.IsNullOrEmpty(assetGUID))
{ {
removeList.Add(assetPath); removeList.Add(assetPath);

View File

@@ -296,6 +296,7 @@ namespace YooAsset.Editor
string filePath = $"{resultPath}/{nameof(DebugReport)}_{_currentReport.FrameCount}.json"; string filePath = $"{resultPath}/{nameof(DebugReport)}_{_currentReport.FrameCount}.json";
string fileContent = JsonUtility.ToJson(_currentReport, true); string fileContent = JsonUtility.ToJson(_currentReport, true);
FileUtility.WriteAllText(filePath, fileContent); FileUtility.WriteAllText(filePath, fileContent);
Debug.Log($"Debug report file saved : {filePath}");
} }
} }
private void OnSearchKeyWordChange(ChangeEvent<string> e) private void OnSearchKeyWordChange(ChangeEvent<string> e)

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); var cell = new ButtonCell(searchTag);
Cells.Add(cell); 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); Cells.Add(cell);
} }
public void AddStringValueCell(string searchTag, string value) public void AddStringValueCell(string searchTag, string value)

View File

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

View File

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

View File

@@ -122,7 +122,7 @@ namespace YooAsset
{ {
if (_disableUnityWebCache) if (_disableUnityWebCache)
{ {
var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, 0); var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, Bundle.UnityCRC);
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
downloadhandler.autoLoadAssetBundle = false; downloadhandler.autoLoadAssetBundle = false;
#endif #endif
@@ -132,9 +132,8 @@ namespace YooAsset
{ {
// 注意:优先从浏览器缓存里获取文件 // 注意:优先从浏览器缓存里获取文件
// The file hash defining the version of the asset bundle. // The file hash defining the version of the asset bundle.
uint unityCRC = Bundle.UnityCRC;
Hash128 fileHash = Hash128.Parse(Bundle.FileHash); Hash128 fileHash = Hash128.Parse(Bundle.FileHash);
var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, fileHash, unityCRC); var downloadhandler = new DownloadHandlerAssetBundle(_requestURL, fileHash, Bundle.UnityCRC);
#if UNITY_2020_3_OR_NEWER #if UNITY_2020_3_OR_NEWER
downloadhandler.autoLoadAssetBundle = false; downloadhandler.autoLoadAssetBundle = false;
#endif #endif

View File

@@ -34,6 +34,20 @@ namespace YooAsset
return str.Remove(index); //"assets/config/test.unity3d" --> "assets/config/test" 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>
/// 合并路径 /// 合并路径
/// </summary> /// </summary>

View File

@@ -63,6 +63,29 @@ namespace YooAsset
} }
} }
/// <summary>
/// 销毁资源系统
/// </summary>
public static void Destroy()
{
if (_isInitialize)
{
_isInitialize = false;
if (_driver != null)
GameObject.Destroy(_driver);
// 终止并清空所有包裹的异步操作
ClearAllPackageOperation();
// 卸载所有AssetBundle
AssetBundle.UnloadAllAssetBundles(true);
// 清空资源包裹列表
_packages.Clear();
}
}
/// <summary> /// <summary>
/// 更新资源系统 /// 更新资源系统
/// </summary> /// </summary>
@@ -75,11 +98,10 @@ namespace YooAsset
} }
/// <summary> /// <summary>
/// 应用程序退出处理 /// 终止并清空所有包裹的异步操作
/// </summary> /// </summary>
internal static void OnApplicationQuit() internal static void ClearAllPackageOperation()
{ {
// 说明在编辑器下确保播放被停止时IO类操作被终止。
foreach (var package in _packages) foreach (var package in _packages)
{ {
OperationSystem.ClearPackageOperation(package.PackageName); OperationSystem.ClearPackageOperation(package.PackageName);

View File

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

View File

@@ -1,4 +1,4 @@
#if UNITY_EDITOR #if UNITY_EDITOR && UNITY_2021_3_OR_NEWER
using System.IO; using System.IO;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@@ -6,6 +6,11 @@ using UnityEngine.U2D;
public static class UIPanelSettings public static class UIPanelSettings
{ {
/// <summary>
/// 是否开启面板监测
/// </summary>
public static bool EnablePanelMonitor = false;
/// <summary> /// <summary>
/// 面板文件夹GUID /// 面板文件夹GUID
/// </summary> /// </summary>
@@ -60,6 +65,9 @@ public class UIPanelMonitor : UnityEditor.Editor
static void OnPrefabSaving(GameObject go) static void OnPrefabSaving(GameObject go)
{ {
if (UIPanelSettings.EnablePanelMonitor == false)
return;
UnityEditor.SceneManagement.PrefabStage stage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage(); UnityEditor.SceneManagement.PrefabStage stage = UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage();
if (stage != null) if (stage != null)
{ {
@@ -78,7 +86,7 @@ public class UIPanelMonitor : UnityEditor.Editor
/// <summary> /// <summary>
/// 刷新面板清单 /// 刷新面板清单
/// </summary> /// </summary>
public static void RefreshPanelManifest(PanelManifest manifest) private static void RefreshPanelManifest(PanelManifest manifest)
{ {
manifest.ReferencesAtlas.Clear(); manifest.ReferencesAtlas.Clear();

View File

@@ -2,9 +2,7 @@
"name": "YooAsset.RuntimeExtension", "name": "YooAsset.RuntimeExtension",
"rootNamespace": "", "rootNamespace": "",
"references": [ "references": [
"GUID:e34a5702dd353724aa315fb8011f08c3", "GUID:e34a5702dd353724aa315fb8011f08c3"
"GUID:5efd170ecd8084500bed5692932fe14e",
"GUID:bb21d6197862c4c3e863390dec9859a7"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

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

View File

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

View File

@@ -11,14 +11,16 @@ internal class TTFSRequestPackageVersionOperation : FSRequestPackageVersionOpera
} }
private readonly TiktokFileSystem _fileSystem; private readonly TiktokFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout; private readonly int _timeout;
private RequestTiktokPackageVersionOperation _requestPackageVersionOp; private RequestTiktokPackageVersionOperation _requestPackageVersionOp;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;
internal TTFSRequestPackageVersionOperation(TiktokFileSystem fileSystem, int timeout) internal TTFSRequestPackageVersionOperation(TiktokFileSystem fileSystem, bool appendTimeTicks, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout; _timeout = timeout;
} }
internal override void InternalStart() internal override void InternalStart()
@@ -34,7 +36,7 @@ internal class TTFSRequestPackageVersionOperation : FSRequestPackageVersionOpera
{ {
if (_requestPackageVersionOp == null) if (_requestPackageVersionOp == null)
{ {
_requestPackageVersionOp = new RequestTiktokPackageVersionOperation(_fileSystem, _timeout); _requestPackageVersionOp = new RequestTiktokPackageVersionOperation(_fileSystem, _appendTimeTicks, _timeout);
_requestPackageVersionOp.StartOperation(); _requestPackageVersionOp.StartOperation();
AddChildOperation(_requestPackageVersionOp); AddChildOperation(_requestPackageVersionOp);
} }

View File

@@ -11,6 +11,7 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
} }
private readonly TiktokFileSystem _fileSystem; private readonly TiktokFileSystem _fileSystem;
private readonly bool _appendTimeTicks;
private readonly int _timeout; private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp; private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0; private int _requestCount = 0;
@@ -21,10 +22,11 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
/// </summary> /// </summary>
public string PackageVersion { private set; get; } public string PackageVersion { private set; get; }
public RequestTiktokPackageVersionOperation(TiktokFileSystem fileSystem, int timeout) public RequestTiktokPackageVersionOperation(TiktokFileSystem fileSystem, bool appendTimeTicks, int timeout)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appendTimeTicks = appendTimeTicks;
_timeout = timeout; _timeout = timeout;
} }
internal override void InternalStart() internal override void InternalStart()
@@ -80,11 +82,19 @@ internal class RequestTiktokPackageVersionOperation : AsyncOperationBase
private string GetRequestURL(string fileName) private string GetRequestURL(string fileName)
{ {
string url;
// 轮流返回请求地址 // 轮流返回请求地址
if (_requestCount % 2 == 0) if (_requestCount % 2 == 0)
return _fileSystem.RemoteServices.GetRemoteMainURL(fileName); url = _fileSystem.RemoteServices.GetRemoteMainURL(fileName);
else else
return _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName); url = _fileSystem.RemoteServices.GetRemoteFallbackURL(fileName);
// 在URL末尾添加时间戳
if (_appendTimeTicks)
return $"{url}?{System.DateTime.UtcNow.Ticks}";
else
return url;
} }
} }
#endif #endif

View File

@@ -121,7 +121,7 @@ internal class TiktokFileSystem : IFileSystem
} }
public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout) public virtual FSRequestPackageVersionOperation RequestPackageVersionAsync(bool appendTimeTicks, int timeout)
{ {
var operation = new TTFSRequestPackageVersionOperation(this, timeout); var operation = new TTFSRequestPackageVersionOperation(this, appendTimeTicks, timeout);
return operation; return operation;
} }
public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, ClearCacheFilesOptions options) public virtual FSClearCacheFilesOperation ClearCacheFilesAsync(PackageManifest manifest, ClearCacheFilesOptions options)

View File

@@ -11,8 +11,8 @@ internal class RequestWechatPackageVersionOperation : AsyncOperationBase
} }
private readonly WechatFileSystem _fileSystem; private readonly WechatFileSystem _fileSystem;
private readonly int _timeout;
private readonly bool _appendTimeTicks; private readonly bool _appendTimeTicks;
private readonly int _timeout;
private UnityWebTextRequestOperation _webTextRequestOp; private UnityWebTextRequestOperation _webTextRequestOp;
private int _requestCount = 0; private int _requestCount = 0;
private ESteps _steps = ESteps.None; private ESteps _steps = ESteps.None;

View File

@@ -198,6 +198,15 @@ internal class WechatFileSystem : IFileSystem
RemoteServices = new WebRemoteServices(webRoot); RemoteServices = new WebRemoteServices(webRoot);
} }
// 检查URL双斜杠
// 注意:双斜杠会导致微信插件加载文件失败,但网络请求又不返回失败!
{
var mainURL = RemoteServices.GetRemoteMainURL("test.bundle");
var fallbackURL = RemoteServices.GetRemoteFallbackURL("test.bundle");
if (PathUtility.HasDoubleSlashes(mainURL) || PathUtility.HasDoubleSlashes(fallbackURL))
throw new Exception($"{nameof(RemoteServices)} returned URL contains double slashes. !");
}
_fileSystemMgr = WX.GetFileSystemManager(); _fileSystemMgr = WX.GetFileSystemManager();
} }
public virtual void OnDestroy() public virtual void OnDestroy()

View File

@@ -0,0 +1,18 @@
{
"name": "YooAsset.MiniGame",
"rootNamespace": "",
"references": [
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:5efd170ecd8084500bed5692932fe14e",
"GUID:bb21d6197862c4c3e863390dec9859a7"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 839b8c2cb327b8a43afe86fd33563571
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 300 KiB

View File

@@ -1,7 +1,7 @@
{ {
"name": "com.tuyoogame.yooasset", "name": "com.tuyoogame.yooasset",
"displayName": "YooAsset", "displayName": "YooAsset",
"version": "2.3.8", "version": "2.3.9",
"unity": "2019.4", "unity": "2019.4",
"description": "unity3d resources management system.", "description": "unity3d resources management system.",
"author": { "author": {
@@ -14,6 +14,11 @@
"description": "YooAsset runtime sample, Include resource update, resource download, resource loading and other functions.", "description": "YooAsset runtime sample, Include resource update, resource download, resource loading and other functions.",
"path": "Samples~/Space Shooter" "path": "Samples~/Space Shooter"
}, },
{
"displayName": "Mini Game",
"description": "YooAsset extension file system, Include wechat file system, tiktok file system.",
"path": "Samples~/Mini Game"
},
{ {
"displayName": "Extension Sample", "displayName": "Extension Sample",
"description": "YooAsset extension sample, Include patcher combine, patcher compare, patcher importer and other functions.", "description": "YooAsset extension sample, Include patcher combine, patcher compare, patcher importer and other functions.",