Compare commits

...

13 Commits
1.0.4 ... 1.0.5

Author SHA1 Message Date
hevinci
469d73d641 Update CHANGELOG.md 2022-04-22 18:16:31 +08:00
hevinci
0d521c68bd Update package.json 2022-04-22 18:16:25 +08:00
hevinci
cd62c1dd9a Update AssetSystem 2022-04-22 16:43:09 +08:00
hevinci
e6422445a6 Added debugging information
新增调试信息,出生场景和出生时间。
2022-04-22 16:22:09 +08:00
hevinci
7683746032 Support do a dry run build.
支持演练构建模式。
2022-04-22 15:14:37 +08:00
hevinci
a25fd19bcc Fixed an issue with task asyn loading waiting 2022-04-21 21:55:48 +08:00
hevinci
6675e8f171 Fixed an issue with task asyn loading waiting 2022-04-21 21:39:00 +08:00
hevinci
c836dce54d Fixed an issue with task asyn loading waiting
修复Task异步加载一直等待的问题。
2022-04-21 21:27:53 +08:00
hevinci
f3ab8f63e7 Optimize the scene unload logic.
优化场景卸载逻辑,在加载新的主场景的时候自动卸载已经加载的所有场景。
2022-04-21 21:11:11 +08:00
hevinci
20d2c517b2 Optimized raw file load logic
优化原生文件加载逻辑,支持离线运行模式和编辑器运行模式。
2022-04-21 16:16:40 +08:00
hevinci
d6a2b31d5c Add editor extend properties
增加编辑器扩展的支持
2022-04-19 10:11:24 +08:00
hevinci
533f96361a Update AssetBundleWindow
修复了非主动收集的着色器没有打进统一的着色器资源包的问题。
修复了单个收集的资源对象没有设置依赖资源列表的问题。
资源打包的过滤文件列表增加cginc格式。
2022-04-18 19:48:37 +08:00
hevinci
09807901c0 Update README.md 2022-04-18 16:01:48 +08:00
43 changed files with 917 additions and 367 deletions

View File

@@ -2,6 +2,23 @@
All notable changes to this package will be documented in this file.
## [1.0.5] - 2022-04-22
### Fixed
- 修复了非主动收集的着色器没有打进统一的着色器资源包的问题。
- 修复了单个收集的资源对象没有设置依赖资源列表的问题。
- 修复Task异步加载一直等待的问题。
### Changed
- 资源打包的过滤文件列表增加cginc格式。
- 增加编辑器扩展的支持第三方实现YooAsset插件。
- 优化原生文件加载逻辑,支持离线运行模式和编辑器运行模式。
- 优化场景卸载逻辑,在加载新的主场景的时候自动卸载已经加载的所有场景。
- 支持演练构建模式,在不生成资源包的情况下快速构建查看结果。
- 新增调试信息,出生场景和出生时间。
## [1.0.4] - 2022-04-18
### Fixed

View File

@@ -48,6 +48,12 @@ namespace YooAsset.Editor
BuildAssetBundleOptions opt = BuildAssetBundleOptions.None;
opt |= BuildAssetBundleOptions.StrictMode; //Do not allow the build to succeed if any errors are reporting during it.
if (Parameters.DryRunBuild)
{
opt |= BuildAssetBundleOptions.DryRunBuild;
return opt;
}
if (Parameters.CompressOption == ECompressOption.Uncompressed)
opt |= BuildAssetBundleOptions.UncompressedAssetBundle;
else if (Parameters.CompressOption == ECompressOption.LZ4)
@@ -107,7 +113,8 @@ namespace YooAsset.Editor
{
new TaskPrepare(), //前期准备工作
new TaskGetBuildMap(), //获取构建列表
new TaskBuilding(), //开始执行构建
new TaskBuilding(), //开始执行构建
new TaskVerifyBuildResult(), //验证构建结果
new TaskEncryption(), //加密资源文件
new TaskCreatePatchManifest(), //创建清单文件
new TaskCreateReport(), //创建报告文件

View File

@@ -31,6 +31,11 @@ namespace YooAsset.Editor
/// </summary>
public bool IsCollectAsset { private set; get; }
/// <summary>
/// 是否为着色器资源
/// </summary>
public bool IsShaderAsset { private set; get; }
/// <summary>
/// 被依赖次数
/// </summary>
@@ -54,6 +59,12 @@ namespace YooAsset.Editor
IsRawAsset = isRawAsset;
NotWriteToAssetList = notWriteToAssetList;
IsCollectAsset = true;
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
IsShaderAsset = true;
else
IsShaderAsset = false;
}
public BuildAssetInfo(string assetPath)
{
@@ -61,6 +72,12 @@ namespace YooAsset.Editor
IsRawAsset = false;
NotWriteToAssetList = true;
IsCollectAsset = false;
System.Type assetType = UnityEditor.AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
IsShaderAsset = true;
else
IsShaderAsset = false;
}
/// <summary>
@@ -82,7 +99,7 @@ namespace YooAsset.Editor
if (string.IsNullOrEmpty(BundleName) == false)
throw new System.Exception("Should never get here !");
BundleName = bundleName;
BundleName = bundleName;
}
/// <summary>
@@ -99,7 +116,7 @@ namespace YooAsset.Editor
/// <summary>
/// 添加资源分类标签
/// </summary>
public void AddAssetTag(string tag)
public void AddAssetTag(string tag)
{
if (AssetTags.Contains(tag) == false)
{

View File

@@ -26,7 +26,7 @@ namespace YooAsset.Editor
{
if (buildAssetDic.ContainsKey(collectAssetInfo.AssetPath) == false)
{
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.AssetPath, collectAssetInfo.IsRawAsset, collectAssetInfo.NotWriteToAssetList);
var buildAssetInfo = new BuildAssetInfo(collectAssetInfo.AssetPath, collectAssetInfo.IsRawAsset, collectAssetInfo.NotWriteToAssetList);
buildAssetInfo.SetBundleName(collectAssetInfo.BundleName);
buildAssetInfo.AddAssetTags(collectAssetInfo.AssetTags);
buildAssetDic.Add(collectAssetInfo.AssetPath, buildAssetInfo);
@@ -78,6 +78,13 @@ namespace YooAsset.Editor
var buildAssetInfo = pair.Value;
if (buildAssetInfo.IsCollectAsset)
continue;
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
if (buildAssetInfo.IsShaderAsset)
continue;
}
if (buildAssetInfo.DependCount == 0)
removeList.Add(buildAssetInfo);
}
@@ -93,9 +100,17 @@ namespace YooAsset.Editor
var buildAssetInfo = pair.Value;
if (buildAssetInfo.BundleNameIsValid() == false)
{
string bundleName = defaultPackRule.GetBundleName(new PackRuleData(buildAssetInfo.AssetPath));
bundleName = AssetBundleCollector.RevisedBundleName(bundleName, false);
buildAssetInfo.SetBundleName(bundleName);
string shaderBundleName = AssetBundleCollector.CollectShaderBundleName(buildAssetInfo.AssetPath);
if (string.IsNullOrEmpty(shaderBundleName) == false)
{
buildAssetInfo.SetBundleName(shaderBundleName);
}
else
{
string bundleName = defaultPackRule.GetBundleName(new PackRuleData(buildAssetInfo.AssetPath));
bundleName = AssetBundleCollector.CorrectBundleName(bundleName, false);
buildAssetInfo.SetBundleName(bundleName);
}
}
}

View File

@@ -46,6 +46,11 @@ namespace YooAsset.Editor
public IEncryptionServices EncryptionServices;
/// <summary>
/// 演练构建模式
/// </summary>
public bool DryRunBuild;
/// <summary>
/// 强制重新构建整个项目如果为FALSE则是增量打包
/// </summary>

View File

@@ -59,6 +59,7 @@ namespace YooAsset.Editor
public string EncryptionServicesClassName;
// 构建参数
public bool DryRunBuild;
public bool ForceRebuild;
public string BuildinTags;
public ECompressOption CompressOption;

View File

@@ -28,7 +28,8 @@ namespace YooAsset.Editor
}
catch (Exception e)
{
Debug.LogError($"Build task {task.GetType().Name} failed : {e}");
Debug.LogError($"Build task {task.GetType().Name} failed !");
Debug.LogError($"Detail error : {e}");
succeed = false;
break;
}

View File

@@ -31,164 +31,29 @@ namespace YooAsset.Editor
context.SetContextObject(unityManifestContext);
// 拷贝原生文件
if (buildParametersContext.Parameters.DryRunBuild == false)
{
CopyRawBundle(buildMapContext, buildParametersContext);
}
}
/// <summary>
/// 拷贝原生文件
/// </summary>
private void CopyRawBundle(BuildMapContext buildMapContext, AssetBundleBuilder.BuildParametersContext buildParametersContext)
{
foreach (var bundleInfo in buildMapContext.BundleInfos)
{
if (bundleInfo.IsRawFile)
{
string dest = $"{buildParametersContext.PipelineOutputDirectory}/{bundleInfo.BundleName}";
foreach(var buildAsset in bundleInfo.BuildinAssets)
foreach (var buildAsset in bundleInfo.BuildinAssets)
{
if(buildAsset.IsRawAsset)
if (buildAsset.IsRawAsset)
EditorTools.CopyFile(buildAsset.AssetPath, dest, true);
}
}
}
// 验证构建结果
if (buildParametersContext.Parameters.VerifyBuildingResult)
{
VerifyingBuildingResult(context, unityManifest);
}
}
/// <summary>
/// 验证构建结果
/// </summary>
private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
{
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
string[] buildedBundles = unityManifest.GetAllAssetBundles();
// 1. 过滤掉原生Bundle
List<BuildBundleInfo> expectBundles = new List<BuildBundleInfo>(buildedBundles.Length);
foreach(var bundleInfo in buildMapContext.BundleInfos)
{
if (bundleInfo.IsRawFile == false)
expectBundles.Add(bundleInfo);
}
// 2. 验证数量
if (buildedBundles.Length != expectBundles.Count)
{
Debug.LogWarning($"构建过程中可能存在无效的资源导致和预期构建的Bundle数量不一致");
}
// 3. 正向验证Bundle
foreach (var bundleName in buildedBundles)
{
if (buildMapContext.IsContainsBundle(bundleName) == false)
{
throw new Exception($"Should never get here !");
}
}
// 4. 反向验证Bundle
bool isPass = true;
foreach (var expectBundle in expectBundles)
{
bool isMatch = false;
foreach (var buildedBundle in buildedBundles)
{
if (buildedBundle == expectBundle.BundleName)
{
isMatch = true;
break;
}
}
if (isMatch == false)
{
isPass = false;
Debug.LogWarning($"没有找到预期构建的Bundle文件 : {expectBundle.BundleName}");
}
}
if(isPass == false)
{
throw new Exception("构建结果验证没有通过,请参考警告日志!");
}
// 5. 验证Asset
int progressValue = 0;
foreach (var buildedBundle in buildedBundles)
{
string filePath = $"{buildParameters.PipelineOutputDirectory}/{buildedBundle}";
string[] allBuildinAssetPaths = GetAssetBundleAllAssets(filePath);
string[] expectBuildinAssetPaths = buildMapContext.GetBuildinAssetPaths(buildedBundle);
if (expectBuildinAssetPaths.Length != allBuildinAssetPaths.Length)
{
Debug.LogWarning($"构建的Bundle文件内的资源对象数量和预期不匹配 : {buildedBundle}");
isPass = false;
continue;
}
foreach (var buildinAssetPath in allBuildinAssetPaths)
{
var guid = AssetDatabase.AssetPathToGUID(buildinAssetPath);
if (string.IsNullOrEmpty(guid))
{
Debug.LogWarning($"无效的资源路径,请检查路径是否带有特殊符号或中文:{buildinAssetPath}");
isPass = false;
continue;
}
bool isMatch = false;
foreach (var exceptBuildAssetPath in expectBuildinAssetPaths)
{
var guidExcept = AssetDatabase.AssetPathToGUID(exceptBuildAssetPath);
if (guid == guidExcept)
{
isMatch = true;
break;
}
}
if (isMatch == false)
{
Debug.LogWarning($"在构建的Bundle文件里发现了没有匹配的资源对象{buildinAssetPath}");
isPass = false;
continue;
}
}
EditorTools.DisplayProgressBar("验证构建结果", ++progressValue, buildedBundles.Length);
}
EditorTools.ClearProgressBar();
if (isPass == false)
{
throw new Exception("构建结果验证没有通过,请参考警告日志!");
}
// 卸载所有加载的Bundle
Debug.Log("构建结果验证成功!");
}
/// <summary>
/// 解析.manifest文件并获取资源列表
/// </summary>
private string[] GetAssetBundleAllAssets(string filePath)
{
string manifestFilePath = $"{filePath}.manifest";
List<string> assetLines = new List<string>();
using (StreamReader reader = File.OpenText(manifestFilePath))
{
string content;
bool findTarget = false;
while (null != (content = reader.ReadLine()))
{
if (content.StartsWith("Dependencies:"))
break;
if (findTarget == false && content.StartsWith("Assets:"))
findTarget = true;
if (findTarget)
{
if (content.StartsWith("- "))
{
string assetPath = content.TrimStart("- ".ToCharArray());
assetLines.Add(assetPath);
}
}
}
}
return assetLines.ToArray();
}
}
}

View File

@@ -15,7 +15,7 @@ namespace YooAsset.Editor
{
// 注意:我们只有在强制重建的时候才会拷贝
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
if (buildParameters.Parameters.ForceRebuild)
if (buildParameters.Parameters.DryRunBuild == false && buildParameters.Parameters.ForceRebuild)
{
// 清空流目录
AssetBundleBuilderHelper.ClearStreamingAssetsFolder();

View File

@@ -62,14 +62,14 @@ namespace YooAsset.Editor
// 内置标记列表
List<string> buildinTags = buildParameters.Parameters.GetBuildinTags();
bool dryRunBuild = buildParameters.Parameters.DryRunBuild;
foreach (var bundleInfo in buildMapContext.BundleInfos)
{
var bundleName = bundleInfo.BundleName;
string filePath = $"{buildParameters.PipelineOutputDirectory}/{bundleName}";
string hash = HashUtility.FileMD5(filePath);
string crc32 = HashUtility.FileCRC32(filePath);
long size = FileUtility.GetFileSize(filePath);
int version = buildParameters.Parameters.BuildVersion;
string hash = GetFileHash(filePath, dryRunBuild);
string crc32 = GetFileCRC(filePath, dryRunBuild);
long size = GetFileSize(filePath, dryRunBuild);
string[] tags = buildMapContext.GetAssetTags(bundleName);
bool isEncrypted = encryptionContext.IsEncryptFile(bundleName);
bool isBuildin = IsBuildinBundle(tags, buildinTags);
@@ -101,6 +101,27 @@ namespace YooAsset.Editor
}
return false;
}
private string GetFileHash(string filePath, bool dryRunBuild)
{
if (dryRunBuild)
return "00000000000000000000000000000000"; //32位
else
return HashUtility.FileMD5(filePath);
}
private string GetFileCRC(string filePath, bool dryRunBuild)
{
if (dryRunBuild)
return "00000000"; //8位
else
return HashUtility.FileCRC32(filePath);
}
private long GetFileSize(string filePath, bool dryRunBuild)
{
if (dryRunBuild)
return 0;
else
return FileUtility.GetFileSize(filePath);
}
/// <summary>
/// 获取资源列表

View File

@@ -11,7 +11,10 @@ namespace YooAsset.Editor
void IBuildTask.Run(BuildContext context)
{
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
CopyPatchFiles(buildParameters);
if (buildParameters.Parameters.DryRunBuild == false)
{
CopyPatchFiles(buildParameters);
}
}
/// <summary>

View File

@@ -35,8 +35,9 @@ namespace YooAsset.Editor
buildReport.Summary.ShadersBundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
buildReport.Summary.EncryptionServicesClassName = buildParameters.Parameters.EncryptionServices == null ?
"null" : buildParameters.Parameters.EncryptionServices.GetType().FullName;
// 构建参数
buildReport.Summary.DryRunBuild = buildParameters.Parameters.DryRunBuild;
buildReport.Summary.ForceRebuild = buildParameters.Parameters.ForceRebuild;
buildReport.Summary.BuildinTags = buildParameters.Parameters.BuildinTags;
buildReport.Summary.CompressOption = buildParameters.Parameters.CompressOption;

View File

@@ -26,9 +26,18 @@ namespace YooAsset.Editor
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
EncryptionContext encryptionContext = new EncryptionContext();
encryptionContext.EncryptList = EncryptFiles(buildParameters, buildMapContext);
context.SetContextObject(encryptionContext);
if (buildParameters.Parameters.DryRunBuild)
{
EncryptionContext encryptionContext = new EncryptionContext();
encryptionContext.EncryptList = new List<string>();
context.SetContextObject(encryptionContext);
}
else
{
EncryptionContext encryptionContext = new EncryptionContext();
encryptionContext.EncryptList = EncryptFiles(buildParameters, buildMapContext);
context.SetContextObject(encryptionContext);
}
}
/// <summary>

View File

@@ -0,0 +1,168 @@
using System;
using System.Linq;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace YooAsset.Editor
{
public class TaskVerifyBuildResult : IBuildTask
{
void IBuildTask.Run(BuildContext context)
{
var buildParametersContext = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
var unityManifestContext = context.GetContextObject<TaskBuilding.UnityManifestContext>();
// 验证构建结果
if (buildParametersContext.Parameters.VerifyBuildingResult)
{
VerifyingBuildingResult(context, unityManifestContext.UnityManifest);
}
}
/// <summary>
/// 验证构建结果
/// </summary>
private void VerifyingBuildingResult(BuildContext context, AssetBundleManifest unityManifest)
{
var buildParameters = context.GetContextObject<AssetBundleBuilder.BuildParametersContext>();
var buildMapContext = context.GetContextObject<BuildMapContext>();
string[] buildedBundles = unityManifest.GetAllAssetBundles();
// 1. 过滤掉原生Bundle
List<BuildBundleInfo> expectBundles = new List<BuildBundleInfo>(buildedBundles.Length);
foreach(var bundleInfo in buildMapContext.BundleInfos)
{
if (bundleInfo.IsRawFile == false)
expectBundles.Add(bundleInfo);
}
// 2. 验证数量
if (buildedBundles.Length != expectBundles.Count)
{
Debug.LogWarning($"构建过程中可能存在无效的资源导致和预期构建的Bundle数量不一致");
}
// 3. 正向验证Bundle
foreach (var bundleName in buildedBundles)
{
if (buildMapContext.IsContainsBundle(bundleName) == false)
{
throw new Exception($"Should never get here !");
}
}
// 4. 反向验证Bundle
bool isPass = true;
foreach (var expectBundle in expectBundles)
{
bool isMatch = false;
foreach (var buildedBundle in buildedBundles)
{
if (buildedBundle == expectBundle.BundleName)
{
isMatch = true;
break;
}
}
if (isMatch == false)
{
isPass = false;
Debug.LogWarning($"没有找到预期构建的Bundle文件 : {expectBundle.BundleName}");
}
}
if(isPass == false)
{
throw new Exception("构建结果验证没有通过,请参考警告日志!");
}
// 5. 验证Asset
if(buildParameters.Parameters.DryRunBuild == false)
{
int progressValue = 0;
foreach (var buildedBundle in buildedBundles)
{
string filePath = $"{buildParameters.PipelineOutputDirectory}/{buildedBundle}";
string[] allBuildinAssetPaths = GetAssetBundleAllAssets(filePath);
string[] expectBuildinAssetPaths = buildMapContext.GetBuildinAssetPaths(buildedBundle);
if (expectBuildinAssetPaths.Length != allBuildinAssetPaths.Length)
{
Debug.LogWarning($"构建的Bundle文件内的资源对象数量和预期不匹配 : {buildedBundle}");
isPass = false;
continue;
}
foreach (var buildinAssetPath in allBuildinAssetPaths)
{
var guid = AssetDatabase.AssetPathToGUID(buildinAssetPath);
if (string.IsNullOrEmpty(guid))
{
Debug.LogWarning($"无效的资源路径,请检查路径是否带有特殊符号或中文:{buildinAssetPath}");
isPass = false;
continue;
}
bool isMatch = false;
foreach (var exceptBuildAssetPath in expectBuildinAssetPaths)
{
var guidExcept = AssetDatabase.AssetPathToGUID(exceptBuildAssetPath);
if (guid == guidExcept)
{
isMatch = true;
break;
}
}
if (isMatch == false)
{
Debug.LogWarning($"在构建的Bundle文件里发现了没有匹配的资源对象{buildinAssetPath}");
isPass = false;
continue;
}
}
EditorTools.DisplayProgressBar("验证构建结果", ++progressValue, buildedBundles.Length);
}
EditorTools.ClearProgressBar();
if (isPass == false)
{
throw new Exception("构建结果验证没有通过,请参考警告日志!");
}
}
// 卸载所有加载的Bundle
Debug.Log("构建结果验证成功!");
}
/// <summary>
/// 解析.manifest文件并获取资源列表
/// </summary>
private string[] GetAssetBundleAllAssets(string filePath)
{
string manifestFilePath = $"{filePath}.manifest";
List<string> assetLines = new List<string>();
using (StreamReader reader = File.OpenText(manifestFilePath))
{
string content;
bool findTarget = false;
while (null != (content = reader.ReadLine()))
{
if (content.StartsWith("Dependencies:"))
break;
if (findTarget == false && content.StartsWith("Assets:"))
findTarget = true;
if (findTarget)
{
if (content.StartsWith("- "))
{
string assetPath = content.TrimStart("- ".ToCharArray());
assetLines.Add(assetPath);
}
}
}
}
return assetLines.ToArray();
}
}
}

View File

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

View File

@@ -114,7 +114,7 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 100;
label.style.width = 150;
element.Add(label);
}
@@ -124,6 +124,26 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 150;
element.Add(label);
}
{
var label = new Label();
label.name = "Label4";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 100;
element.Add(label);
}
{
var label = new Label();
label.name = "Label5";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 120;
element.Add(label);
}
@@ -139,9 +159,17 @@ namespace YooAsset.Editor
var label1 = element.Q<Label>("Label1");
label1.text = providerInfo.AssetPath;
// Ref Count
// Spawn Scene
var label2 = element.Q<Label>("Label2");
label2.text = providerInfo.RefCount.ToString();
label2.text = providerInfo.SpawnScene;
// Spawn Time
var label3 = element.Q<Label>("Label3");
label3.text = providerInfo.SpawnTime;
// Ref Count
var label4 = element.Q<Label>("Label4");
label4.text = providerInfo.RefCount.ToString();
// Status
StyleColor textColor;
@@ -149,9 +177,9 @@ namespace YooAsset.Editor
textColor = new StyleColor(Color.yellow);
else
textColor = label1.style.color;
var label3 = element.Q<Label>("Label3");
label3.text = providerInfo.Status.ToString();
label3.style.color = textColor;
var label5 = element.Q<Label>("Label5");
label5.text = providerInfo.Status.ToString();
label5.style.color = textColor;
}
private void AssetListView_onSelectionChange(IEnumerable<object> objs)
{

View File

@@ -2,8 +2,10 @@
<ui:VisualElement name="TopGroup" style="flex-grow: 1; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 2px; margin-bottom: 1px; display: flex;">
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Asset Path" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="TopBar3" style="width: 120px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Spawn Scene" display-tooltip-when-elided="true" name="TopBar2" style="width: 150px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Spawn Time" display-tooltip-when-elided="true" name="TopBar3" style="width: 150px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="TopBar4" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="TopBar5" style="width: 120px; -unity-text-align: middle-left;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
</ui:VisualElement>

View File

@@ -65,14 +65,14 @@ namespace YooAsset.Editor
Dictionary<string, DebugBundleInfo> result = new Dictionary<string, DebugBundleInfo>(debugReport.ProviderInfos.Count);
foreach (var providerInfo in debugReport.ProviderInfos)
{
foreach(var bundleInfo in providerInfo.BundleInfos)
foreach (var bundleInfo in providerInfo.BundleInfos)
{
if (string.IsNullOrEmpty(searchKeyWord) == false)
{
if (bundleInfo.BundleName.Contains(searchKeyWord) == false)
continue;
}
if(result.ContainsKey(bundleInfo.BundleName) == false)
if (result.ContainsKey(bundleInfo.BundleName) == false)
result.Add(bundleInfo.BundleName, bundleInfo);
}
}
@@ -95,7 +95,7 @@ namespace YooAsset.Editor
_root.RemoveFromHierarchy();
}
// 顶部列表相关
private VisualElement MakeAssetListViewItem()
{
@@ -188,7 +188,7 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 100;
label.style.width = 150;
element.Add(label);
}
@@ -198,10 +198,30 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 150;
element.Add(label);
}
{
var label = new Label();
label.name = "Label4";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 100;
element.Add(label);
}
{
var label = new Label();
label.name = "Label5";
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 120;
element.Add(label);
}
return element;
}
private void BindIncludeListViewItem(VisualElement element, int index)
@@ -213,29 +233,37 @@ namespace YooAsset.Editor
var label1 = element.Q<Label>("Label1");
label1.text = providerInfo.AssetPath;
// Ref Count
// Spawn Scene
var label2 = element.Q<Label>("Label2");
label2.text = providerInfo.RefCount.ToString();
label2.text = providerInfo.SpawnScene;
// Spawn Time
var label3 = element.Q<Label>("Label3");
label3.text = providerInfo.SpawnTime;
// Ref Count
var label4 = element.Q<Label>("Label4");
label4.text = providerInfo.RefCount.ToString();
// Status
var label3 = element.Q<Label>("Label3");
label3.text = providerInfo.Status.ToString();
var label5 = element.Q<Label>("Label5");
label5.text = providerInfo.Status.ToString();
}
private void FillUsingListView(string bundleName)
{
_usingListView.Clear();
_usingListView.ClearSelection();
List<DebugProviderInfo> source = new List<DebugProviderInfo>();
foreach(var providerInfo in _debugReport.ProviderInfos)
List<DebugProviderInfo> source = new List<DebugProviderInfo>();
foreach (var providerInfo in _debugReport.ProviderInfos)
{
foreach(var bundleInfo in providerInfo.BundleInfos)
foreach (var bundleInfo in providerInfo.BundleInfos)
{
if (bundleInfo.BundleName == bundleName)
{
source.Add(providerInfo);
continue;
}
}
}
}
_usingListView.itemsSource = source;

View File

@@ -10,8 +10,10 @@
<ui:VisualElement name="BottomGroup" style="height: 200px; border-left-width: 1px; border-right-width: 1px; border-top-width: 1px; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); border-bottom-color: rgb(0, 0, 0); margin-left: 0; margin-right: 0; margin-top: 1px; margin-bottom: 1px; display: flex;">
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Using Assets" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="BottomBar3" style="width: 100px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="BottomBar4" style="width: 120px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Spawn Scene" display-tooltip-when-elided="true" name="BottomBar2" style="width: 150px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Spawn Time" display-tooltip-when-elided="true" name="BottomBar3" style="width: 150px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Ref Count" display-tooltip-when-elided="true" name="BottomBar4" style="width: 100px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Status" display-tooltip-when-elided="true" name="BottomBar5" style="width: 120px; -unity-text-align: middle-left;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
</ui:VisualElement>

View File

@@ -94,6 +94,7 @@ namespace YooAsset.Editor
string bundleName = GetBundleName(grouper, assetPath, isRawAsset);
List<string> assetTags = GetAssetTags(grouper);
var collectAssetInfo = new CollectAssetInfo(bundleName, assetPath, assetTags, isRawAsset, NotWriteToAssetList);
collectAssetInfo.DependAssets = GetAllDependencies(assetPath);
result.Add(assetPath, collectAssetInfo);
}
else
@@ -120,7 +121,7 @@ namespace YooAsset.Editor
return false;
string ext = System.IO.Path.GetExtension(assetPath);
if (ext == "" || ext == ".dll" || ext == ".cs" || ext == ".js" || ext == ".boo" || ext == ".meta")
if (ext == "" || ext == ".dll" || ext == ".cs" || ext == ".js" || ext == ".boo" || ext == ".meta" || ext == ".cginc")
return false;
return true;
@@ -141,22 +142,15 @@ namespace YooAsset.Editor
}
private string GetBundleName(AssetBundleGrouper grouper, string assetPath, bool isRawAsset)
{
// 如果收集全路径着色器
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
{
string bundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
return RevisedBundleName(bundleName, false);
}
}
string shaderBundleName = CollectShaderBundleName(assetPath);
if (string.IsNullOrEmpty(shaderBundleName) == false)
return shaderBundleName;
// 根据规则设置获取资源包名称
{
IPackRule packRuleInstance = AssetBundleGrouperSettingData.GetPackRuleInstance(PackRuleName);
string bundleName = packRuleInstance.GetBundleName(new PackRuleData(assetPath, CollectPath, grouper.GrouperName));
return RevisedBundleName(bundleName, isRawAsset);
return CorrectBundleName(bundleName, isRawAsset);
}
}
private List<string> GetAssetTags(AssetBundleGrouper grouper)
@@ -182,11 +176,28 @@ namespace YooAsset.Editor
return result;
}
/// <summary>
/// 收集着色器的资源包名称
/// </summary>
public static string CollectShaderBundleName(string assetPath)
{
// 如果自动收集所有的着色器
if (AssetBundleGrouperSettingData.Setting.AutoCollectShaders)
{
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Shader))
{
string bundleName = AssetBundleGrouperSettingData.Setting.ShadersBundleName;
return CorrectBundleName(bundleName, false);
}
}
return null;
}
/// <summary>
/// 修正资源包名
/// 修正资源包名
/// </summary>
public static string RevisedBundleName(string bundleName, bool isRawBundle)
public static string CorrectBundleName(string bundleName, bool isRawBundle)
{
if (isRawBundle)
{

View File

@@ -234,7 +234,7 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 250;
label.style.width = 280;
element.Add(label);
}

View File

@@ -11,7 +11,7 @@
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Depend Bundles" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="BottomBar3" style="width: 250px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="BottomBar3" style="width: 280px; -unity-text-align: middle-left;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
</ui:VisualElement>

View File

@@ -145,7 +145,7 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 250;
label.style.width = 280;
element.Add(label);
}
@@ -237,7 +237,7 @@ namespace YooAsset.Editor
label.style.unityTextAlign = TextAnchor.MiddleLeft;
label.style.marginLeft = 3f;
//label.style.flexGrow = 1f;
label.style.width = 250;
label.style.width = 280;
element.Add(label);
}

View File

@@ -4,7 +4,7 @@
<uie:Toolbar name="TopBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Bundle Name" display-tooltip-when-elided="true" name="TopBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="TopBar2" style="width: 100px; -unity-text-align: middle-left; flex-grow: 0;" />
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="TopBar3" style="width: 250px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Hash" display-tooltip-when-elided="true" name="TopBar3" style="width: 280px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar5" style="width: 80px; -unity-text-align: middle-left; flex-grow: 1;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="TopListView" item-height="18" style="flex-grow: 1;" />
@@ -13,7 +13,7 @@
<uie:Toolbar name="BottomBar" style="height: 25px; margin-left: 1px; margin-right: 1px;">
<uie:ToolbarButton text="Include Assets" display-tooltip-when-elided="true" name="BottomBar1" style="width: 280px; -unity-text-align: middle-left; flex-grow: 1;" />
<uie:ToolbarButton text="Size" display-tooltip-when-elided="true" name="BottomBar2" style="width: 100px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="GUID" display-tooltip-when-elided="true" name="BottomBar3" style="width: 250px; -unity-text-align: middle-left;" />
<uie:ToolbarButton text="GUID" display-tooltip-when-elided="true" name="BottomBar3" style="width: 280px; -unity-text-align: middle-left;" />
</uie:Toolbar>
<ui:ListView focusable="true" name="BottomListView" item-height="18" style="flex-grow: 1;" />
</ui:VisualElement>

View File

@@ -76,6 +76,7 @@ namespace YooAsset.Editor
_items.Add(new ItemWrapper(string.Empty, string.Empty));
_items.Add(new ItemWrapper("构建参数", string.Empty));
_items.Add(new ItemWrapper("DryRunBuild", $"{buildReport.Summary.DryRunBuild}"));
_items.Add(new ItemWrapper("ForceRebuild", $"{buildReport.Summary.ForceRebuild}"));
_items.Add(new ItemWrapper("BuildinTags", $"{buildReport.Summary.BuildinTags}"));
_items.Add(new ItemWrapper("CompressOption", $"{buildReport.Summary.CompressOption}"));

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
@@ -10,7 +11,8 @@ namespace YooAsset
{
private static readonly List<AssetBundleLoaderBase> _loaders = new List<AssetBundleLoaderBase>(1000);
private static readonly List<ProviderBase> _providers = new List<ProviderBase>(1000);
private static readonly Dictionary<string, SceneOperationHandle> _sceneHandles = new Dictionary<string, SceneOperationHandle>(100);
/// <summary>
/// 在编辑器下模拟运行
/// </summary>
@@ -127,23 +129,21 @@ namespace YooAsset
}
/// <summary>
/// 异步加载原生文件
/// </summary>
public static RawFileOperation LoadRawFileAsync(string assetPath, string copyPath)
{
string bundleName = BundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = BundleServices.GetBundleInfo(bundleName);
RawFileOperation operation = new RawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
/// <summary>
/// 异步加载场景
/// </summary>
public static SceneOperationHandle LoadSceneAsync(string scenePath, LoadSceneMode sceneMode, bool activateOnLoad, int priority)
{
// 注意:场景句柄永远保持唯一
if (_sceneHandles.ContainsKey(scenePath))
return _sceneHandles[scenePath];
// 如果加载的是主场景,则卸载所有缓存的场景
if (sceneMode == LoadSceneMode.Single)
{
UnloadAllScene();
}
ProviderBase provider = TryGetProvider(scenePath);
if (provider == null)
{
@@ -151,9 +151,13 @@ namespace YooAsset
provider = new DatabaseSceneProvider(scenePath, sceneMode, activateOnLoad, priority);
else
provider = new BundledSceneProvider(scenePath, sceneMode, activateOnLoad, priority);
provider.InitSpawnDebugInfo();
_providers.Add(provider);
}
return provider.CreateHandle() as SceneOperationHandle;
var handle = provider.CreateHandle() as SceneOperationHandle;
_sceneHandles.Add(scenePath, handle);
return handle;
}
/// <summary>
@@ -168,6 +172,7 @@ namespace YooAsset
provider = new DatabaseAssetProvider(assetPath, assetType);
else
provider = new BundledAssetProvider(assetPath, assetType);
provider.InitSpawnDebugInfo();
_providers.Add(provider);
}
return provider.CreateHandle() as AssetOperationHandle;
@@ -185,12 +190,55 @@ namespace YooAsset
provider = new DatabaseSubAssetsProvider(assetPath, assetType);
else
provider = new BundledSubAssetsProvider(assetPath, assetType);
provider.InitSpawnDebugInfo();
_providers.Add(provider);
}
return provider.CreateHandle() as SubAssetsOperationHandle;
}
internal static void UnloadSubScene(ProviderBase provider)
{
string scenePath = provider.AssetPath;
if (_sceneHandles.ContainsKey(scenePath) == false)
throw new Exception("Should never get here !");
// 释放子场景句柄
_sceneHandles[scenePath].ReleaseInternal();
_sceneHandles.Remove(scenePath);
// 卸载未被使用的资源(包括场景)
AssetSystem.UnloadUnusedAssets();
// 检验子场景是否销毁
if (provider.IsDestroyed == false)
{
throw new Exception("Should never get here !");
}
}
internal static void UnloadAllScene()
{
// 释放所有场景句柄
foreach (var valuePair in _sceneHandles)
{
valuePair.Value.ReleaseInternal();
}
_sceneHandles.Clear();
// 卸载未被使用的资源(包括场景)
AssetSystem.UnloadUnusedAssets();
// 检验所有场景是否销毁
foreach (var provider in _providers)
{
if (provider.IsSceneProvider())
{
if (provider.IsDestroyed == false)
throw new Exception("Should never get here !");
}
}
}
internal static AssetBundleLoaderBase CreateOwnerAssetBundleLoader(string assetPath)
{
string bundleName = BundleServices.GetBundleName(assetPath);
@@ -266,6 +314,7 @@ namespace YooAsset
return provider;
}
#region
internal static void GetDebugReport(DebugReport report)
{
@@ -277,6 +326,8 @@ namespace YooAsset
{
DebugProviderInfo providerInfo = new DebugProviderInfo();
providerInfo.AssetPath = provider.AssetPath;
providerInfo.SpawnScene = provider.SpawnScene;
providerInfo.SpawnTime = provider.SpawnTime;
providerInfo.RefCount = provider.RefCount;
providerInfo.Status = provider.Status;
providerInfo.BundleInfos.Clear();

View File

@@ -2,7 +2,7 @@
namespace YooAsset
{
public class AssetOperationHandle : OperationHandleBase
public sealed class AssetOperationHandle : OperationHandleBase
{
private System.Action<AssetOperationHandle> _callback;

View File

@@ -4,11 +4,13 @@ namespace YooAsset
{
public abstract class OperationHandleBase : IEnumerator
{
private readonly string _cachedAssetPath;
internal ProviderBase _provider { private set; get; }
internal OperationHandleBase(ProviderBase provider)
{
_provider = provider;
_cachedAssetPath = provider.AssetPath;
}
internal abstract void InvokeCallback();
@@ -63,7 +65,18 @@ namespace YooAsset
{
get
{
return _provider != null && _provider.IsDestroyed == false;
if (_provider != null && _provider.IsDestroyed == false)
{
return true;
}
else
{
if (_provider == null)
YooLogger.Warning($"Operation handle is released : {_cachedAssetPath}");
else if (_provider.IsDestroyed)
YooLogger.Warning($"Provider is destroyed : {_cachedAssetPath}");
return false;
}
}
}
@@ -82,7 +95,7 @@ namespace YooAsset
/// <summary>
/// 异步操作任务
/// </summary>
public System.Threading.Tasks.Task<object> Task
public System.Threading.Tasks.Task Task
{
get { return _provider.Task; }
}

View File

@@ -69,10 +69,35 @@ namespace YooAsset
}
/// <summary>
/// 异步卸载场景
/// 是否为主场景
/// </summary>
public bool IsMainScene()
{
if (IsValid == false)
return false;
if (_provider is DatabaseSceneProvider)
{
var temp = _provider as DatabaseSceneProvider;
return temp.SceneMode == LoadSceneMode.Single;
}
else if (_provider is BundledSceneProvider)
{
var temp = _provider as BundledSceneProvider;
return temp.SceneMode == LoadSceneMode.Single;
}
else
{
throw new System.NotImplementedException();
}
}
/// <summary>
/// 异步卸载子场景
/// </summary>
public UnloadSceneOperation UnloadAsync()
{
// 如果句柄无效
if (IsValid == false)
{
string error = $"{nameof(SceneOperationHandle)} is invalid.";
@@ -81,54 +106,23 @@ namespace YooAsset
return operation;
}
ProviderBase provider = _provider;
// 释放场景句柄
ReleaseInternal();
// 卸载未被使用的资源(包括场景)
AssetSystem.UnloadUnusedAssets();
// 返回场景卸载异步操作类
if (provider.IsDestroyed == false)
// 如果是主场景
if (IsMainScene())
{
YooLogger.Warning($"Scene can not unload. The provider not destroyed : {provider.AssetPath}");
var operation = new UnloadSceneOperation();
string error = $"Cannot unload main scene. Use {nameof(YooAssets.LoadSceneAsync)} method to change the main scene !";
YooLogger.Error(error);
var operation = new UnloadSceneOperation(error);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else
{
if (IsAdditiveScene(provider))
{
var operation = new UnloadSceneOperation(provider.SceneObject);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else
{
var operation = new UnloadSceneOperation();
OperationSystem.ProcessOperaiton(operation);
return operation;
}
}
}
private bool IsAdditiveScene(ProviderBase provider)
{
if (provider is DatabaseSceneProvider)
// 卸载子场景
Scene sceneObject = SceneObject;
AssetSystem.UnloadSubScene(_provider);
{
var temp = provider as DatabaseSceneProvider;
return temp.SceneMode == LoadSceneMode.Additive;
}
else if (provider is BundledSceneProvider)
{
var temp = provider as BundledSceneProvider;
return temp.SceneMode == LoadSceneMode.Additive;
}
else
{
throw new System.NotImplementedException();
var operation = new UnloadSceneOperation(sceneObject);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
}
}

View File

@@ -1,7 +1,7 @@

namespace YooAsset
{
public class SubAssetsOperationHandle : OperationHandleBase
public sealed class SubAssetsOperationHandle : OperationHandleBase
{
private System.Action<SubAssetsOperationHandle> _callback;

View File

@@ -48,12 +48,15 @@ namespace YooAsset
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(AssetOperationHandle)} is invalid.";
return;
}
if (_handle.AssetObject == null)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"{nameof(AssetOperationHandle.AssetObject)} is null.";
return;
}
if(_setPositionRotation)

View File

@@ -2,49 +2,159 @@
namespace YooAsset
{
public class RawFileOperation : AsyncOperationBase
/// <summary>
/// 原生文件操作
/// </summary>
public abstract class RawFileOperation : AsyncOperationBase
{
private enum ESteps
{
None,
Prepare,
DownloadFromWeb,
CheckDownloadFromWeb,
DownloadFromApk,
CheckDownloadFromApk,
CheckAndCopyFile,
Done,
}
private readonly BundleInfo _bundleInfo;
private ESteps _steps = ESteps.None;
private DownloaderBase _downloader;
private UnityWebFileRequester _fileRequester;
protected readonly BundleInfo _bundleInfo;
/// <summary>
/// 原生文件的拷贝路径
/// </summary>
public string CopyPath { private set; get; }
/// <summary>
/// 原生文件的缓存路径
/// </summary>
public string CachePath
{
get
{
if (_bundleInfo == null)
return string.Empty;
return _bundleInfo.GetCacheLoadPath();
}
}
internal RawFileOperation(BundleInfo bundleInfo, string copyPath)
{
_bundleInfo = bundleInfo;
CopyPath = copyPath;
}
/// <summary>
/// 原生文件的缓存路径
/// </summary>
public abstract string GetCachePath();
/// <summary>
/// 获取原生文件的二进制数据
/// </summary>
public byte[] GetFileData()
{
string filePath = GetCachePath();
if (File.Exists(filePath) == false)
return null;
return File.ReadAllBytes(filePath);
}
/// <summary>
/// 获取原生文件的文本数据
/// </summary>
public string GetFileText()
{
string filePath = GetCachePath();
if (File.Exists(filePath) == false)
return string.Empty;
return File.ReadAllText(filePath, System.Text.Encoding.UTF8);
}
}
/// <summary>
/// 编辑器下模拟运行的原生文件操作
/// </summary>
internal sealed class EditorPlayModeRawFileOperation : RawFileOperation
{
private enum ESteps
{
None,
Prepare,
CheckAndCopyFile,
Done,
}
private ESteps _steps = ESteps.None;
internal EditorPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{
}
internal override void Start()
{
_steps = ESteps.Prepare;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 1. 准备工作
if (_steps == ESteps.Prepare)
{
if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.None)
{
_steps = ESteps.CheckAndCopyFile;
return; // 模拟实现异步操作
}
else
{
throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
}
}
// 2. 检测并拷贝原生文件
if (_steps == ESteps.CheckAndCopyFile)
{
// 如果不需要保存文件
if (string.IsNullOrEmpty(CopyPath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
// 如果原生文件已经存在,则将其删除
if (File.Exists(CopyPath))
{
File.Delete(CopyPath);
}
try
{
FileUtility.CreateFileDirectory(CopyPath);
File.Copy(GetCachePath(), CopyPath, true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (System.Exception e)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = e.ToString();
}
}
}
/// <summary>
/// 原生文件的缓存路径
/// </summary>
public override string GetCachePath()
{
if (_bundleInfo == null)
return string.Empty;
return _bundleInfo.BundleName;
}
}
/// <summary>
/// 离线模式的原生文件操作
/// </summary>
internal sealed class OfflinePlayModeRawFileOperation : RawFileOperation
{
private enum ESteps
{
None,
Prepare,
DownloadFromApk,
CheckDownloadFromApk,
CheckAndCopyFile,
Done,
}
private ESteps _steps = ESteps.None;
private UnityWebFileRequester _fileRequester;
public OfflinePlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{
}
internal override void Start()
{
_steps = ESteps.Prepare;
@@ -62,10 +172,142 @@ namespace YooAsset
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Bundle info is invalid : {_bundleInfo.BundleName}";
}
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
{
_steps = ESteps.DownloadFromApk;
}
else
{
throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
}
}
// 2. 从APK拷贝文件
if (_steps == ESteps.DownloadFromApk)
{
string downloadURL = PathHelper.ConvertToWWWPath(_bundleInfo.GetStreamingLoadPath());
_fileRequester = new UnityWebFileRequester();
_fileRequester.SendRequest(downloadURL, GetCachePath());
_steps = ESteps.CheckDownloadFromApk;
}
// 3. 检测APK拷贝文件结果
if (_steps == ESteps.CheckDownloadFromApk)
{
if (_fileRequester.IsDone() == false)
return;
if (_fileRequester.HasError())
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = _fileRequester.GetError();
}
else
{
_steps = ESteps.CheckAndCopyFile;
}
_fileRequester.Dispose();
}
// 4. 检测并拷贝原生文件
if (_steps == ESteps.CheckAndCopyFile)
{
// 如果不需要保存文件
if (string.IsNullOrEmpty(CopyPath))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
// 如果原生文件已经存在,则验证其完整性
if (File.Exists(CopyPath))
{
bool result = DownloadSystem.CheckContentIntegrity(CopyPath, _bundleInfo.SizeBytes, _bundleInfo.CRC);
if (result)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
return;
}
else
{
File.Delete(CopyPath);
}
}
try
{
FileUtility.CreateFileDirectory(CopyPath);
File.Copy(GetCachePath(), CopyPath, true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
catch (System.Exception e)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = e.ToString();
}
}
}
/// <summary>
/// 原生文件的缓存路径
/// </summary>
public override string GetCachePath()
{
if (_bundleInfo == null)
return string.Empty;
return _bundleInfo.GetCacheLoadPath();
}
}
/// <summary>
/// 网络模式的原生文件操作
/// </summary>
internal sealed class HostPlayModeRawFileOperation : RawFileOperation
{
private enum ESteps
{
None,
Prepare,
DownloadFromWeb,
CheckDownloadFromWeb,
DownloadFromApk,
CheckDownloadFromApk,
CheckAndCopyFile,
Done,
}
private ESteps _steps = ESteps.None;
private DownloaderBase _downloader;
private UnityWebFileRequester _fileRequester;
internal HostPlayModeRawFileOperation(BundleInfo bundleInfo, string copyPath) : base(bundleInfo, copyPath)
{
}
internal override void Start()
{
_steps = ESteps.Prepare;
}
internal override void Update()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 1. 准备工作
if (_steps == ESteps.Prepare)
{
if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.None)
{
_steps = ESteps.Done;
Status = EOperationStatus.Failed;
Error = $"Bundle info is invalid : {_bundleInfo.BundleName}";
}
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
{
_steps = ESteps.DownloadFromWeb;
}
@@ -114,7 +356,7 @@ namespace YooAsset
{
string downloadURL = PathHelper.ConvertToWWWPath(_bundleInfo.GetStreamingLoadPath());
_fileRequester = new UnityWebFileRequester();
_fileRequester.SendRequest(downloadURL, _bundleInfo.GetCacheLoadPath());
_fileRequester.SendRequest(downloadURL, GetCachePath());
_steps = ESteps.CheckDownloadFromApk;
}
@@ -167,7 +409,7 @@ namespace YooAsset
try
{
FileUtility.CreateFileDirectory(CopyPath);
File.Copy(_bundleInfo.GetCacheLoadPath(), CopyPath, true);
File.Copy(GetCachePath(), CopyPath, true);
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
@@ -181,25 +423,13 @@ namespace YooAsset
}
/// <summary>
/// 获取原生文件的二进制数据
/// 原生文件的缓存路径
/// </summary>
public byte[] GetFileData()
public override string GetCachePath()
{
string cachePath = _bundleInfo.GetCacheLoadPath();
if (File.Exists(cachePath) == false)
return null;
return File.ReadAllBytes(cachePath);
}
/// <summary>
/// 获取原生文件的文本数据
/// </summary>
public string GetFileText()
{
string cachePath = _bundleInfo.GetCacheLoadPath();
if (File.Exists(cachePath) == false)
if (_bundleInfo == null)
return string.Empty;
return File.ReadAllText(cachePath, System.Text.Encoding.UTF8);
return _bundleInfo.GetCacheLoadPath();
}
}
}

View File

@@ -12,7 +12,6 @@ namespace YooAsset
{
Normal,
Error,
Skip,
}
private enum ESteps
{
@@ -40,10 +39,6 @@ namespace YooAsset
}
}
internal UnloadSceneOperation()
{
_flag = EFlag.Skip;
}
internal UnloadSceneOperation(string error)
{
_flag = EFlag.Error;
@@ -60,11 +55,6 @@ namespace YooAsset
{
_steps = ESteps.UnLoad;
}
else if (_flag == EFlag.Skip)
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else if (_flag == EFlag.Error)
{
_steps = ESteps.Done;

View File

@@ -1,5 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
namespace YooAsset
{
@@ -197,31 +199,22 @@ namespace YooAsset
/// <summary>
/// 异步操作任务
/// </summary>
public System.Threading.Tasks.Task<object> Task
public Task Task
{
get
{
var handle = WaitHandle;
return System.Threading.Tasks.Task.Factory.StartNew(o =>
if (_taskCompletionSource == null)
{
handle.WaitOne();
return AssetObject as object;
}, this);
_taskCompletionSource = new TaskCompletionSource<object>();
if (IsDone)
_taskCompletionSource.SetResult(null);
}
return _taskCompletionSource.Task;
}
}
#region
private System.Threading.EventWaitHandle _waitHandle;
private System.Threading.WaitHandle WaitHandle
{
get
{
if (_waitHandle == null)
_waitHandle = new System.Threading.EventWaitHandle(false, System.Threading.EventResetMode.ManualReset);
_waitHandle.Reset();
return _waitHandle;
}
}
private TaskCompletionSource<object> _taskCompletionSource;
protected void InvokeCompletion()
{
// 注意:创建临时列表是为了防止外部逻辑在回调函数内创建或者释放资源句柄。
@@ -233,7 +226,35 @@ namespace YooAsset
hande.InvokeCallback();
}
}
_waitHandle?.Set();
if (_taskCompletionSource != null)
_taskCompletionSource.TrySetResult(null);
}
#endregion
#region
/// <summary>
/// 出生的场景
/// </summary>
public string SpawnScene = string.Empty;
/// <summary>
/// 出生的时间
/// </summary>
public string SpawnTime = string.Empty;
[Conditional("DEBUG")]
public void InitSpawnDebugInfo()
{
SpawnScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; ;
SpawnTime = SpawnTimeToString(UnityEngine.Time.realtimeSinceStartup);
}
private string SpawnTimeToString(float spawnTime)
{
float h = UnityEngine.Mathf.FloorToInt(spawnTime / 3600f);
float m = UnityEngine.Mathf.FloorToInt(spawnTime / 60f - h * 60f);
float s = UnityEngine.Mathf.FloorToInt(spawnTime - m * 60f - h * 3600f);
return h.ToString("00") + ":" + m.ToString("00") + ":" + s.ToString("00");
}
#endregion
}

View File

@@ -11,6 +11,16 @@ namespace YooAsset
/// </summary>
public string AssetPath { set; get; }
/// <summary>
/// 资源出生的场景
/// </summary>
public string SpawnScene { set; get; }
/// <summary>
/// 资源出生的时间
/// </summary>
public string SpawnTime { set; get; }
/// <summary>
/// 引用计数
/// </summary>

View File

@@ -1,6 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace YooAsset
@@ -15,7 +14,7 @@ namespace YooAsset
/// <summary>
/// 编辑器下模拟运行的初始化操作
/// </summary>
internal class EditorModeInitializationOperation : InitializationOperation
internal sealed class EditorPlayModeInitializationOperation : InitializationOperation
{
internal override void Start()
{
@@ -29,7 +28,7 @@ namespace YooAsset
/// <summary>
/// 离线模式的初始化操作
/// </summary>
internal class OfflinePlayModeInitializationOperation : InitializationOperation
internal sealed class OfflinePlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
{
@@ -81,7 +80,7 @@ namespace YooAsset
/// <summary>
/// 网络模式的初始化操作
/// </summary>
internal class HostPlayModeInitializationOperation : InitializationOperation
internal sealed class HostPlayModeInitializationOperation : InitializationOperation
{
private enum ESteps
{

View File

@@ -16,7 +16,7 @@ namespace YooAsset
/// <summary>
/// 编辑器下模拟运行的更新清单操作
/// </summary>
internal class EditorModeUpdateManifestOperation : UpdateManifestOperation
internal sealed class EditorPlayModeUpdateManifestOperation : UpdateManifestOperation
{
internal override void Start()
{
@@ -30,7 +30,7 @@ namespace YooAsset
/// <summary>
/// 离线模式的更新清单操作
/// </summary>
internal class OfflinePlayModeUpdateManifestOperation : UpdateManifestOperation
internal sealed class OfflinePlayModeUpdateManifestOperation : UpdateManifestOperation
{
internal override void Start()
{
@@ -44,7 +44,7 @@ namespace YooAsset
/// <summary>
/// 网络模式的更新清单操作
/// </summary>
internal class HostPlayModeUpdateManifestOperation : UpdateManifestOperation
internal sealed class HostPlayModeUpdateManifestOperation : UpdateManifestOperation
{
private enum ESteps
{

View File

@@ -1,7 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace YooAsset
{
@@ -19,7 +17,7 @@ namespace YooAsset
/// <summary>
/// 编辑器下模拟运行的更新静态版本操作
/// </summary>
internal class EditorModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
internal sealed class EditorPlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
{
internal override void Start()
{
@@ -33,7 +31,7 @@ namespace YooAsset
/// <summary>
/// 离线模式的更新静态版本操作
/// </summary>
internal class OfflinePlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
internal sealed class OfflinePlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
{
internal override void Start()
{
@@ -47,7 +45,7 @@ namespace YooAsset
/// <summary>
/// 网络模式的更新静态版本操作
/// </summary>
internal class HostPlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
internal sealed class HostPlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
{
private enum ESteps
{

View File

@@ -11,7 +11,7 @@ namespace YooAsset
/// </summary>
public InitializationOperation InitializeAsync()
{
var operation = new EditorModeInitializationOperation();
var operation = new EditorPlayModeInitializationOperation();
OperationSystem.ProcessOperaiton(operation);
return operation;
}

View File

@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("YooAsset.Editor")]
[assembly: InternalsVisibleTo("YooAsset.Editor")]
[assembly: InternalsVisibleTo("YooAsset.EditorExtend")]

View File

@@ -219,12 +219,11 @@ namespace YooAsset
/// 向网络端请求静态资源版本号
/// </summary>
/// <param name="timeout">超时时间默认值60秒</param>
/// <returns></returns>
public static UpdateStaticVersionOperation UpdateStaticVersionAsync(int timeout = 60)
{
if (_playMode == EPlayMode.EditorPlayMode)
{
var operation = new EditorModeUpdateStaticVersionOperation();
var operation = new EditorPlayModeUpdateStaticVersionOperation();
OperationSystem.ProcessOperaiton(operation);
return operation;
}
@@ -255,7 +254,7 @@ namespace YooAsset
{
if (_playMode == EPlayMode.EditorPlayMode)
{
var operation = new EditorModeUpdateManifestOperation();
var operation = new EditorPlayModeUpdateManifestOperation();
OperationSystem.ProcessOperaiton(operation);
return operation;
}
@@ -369,7 +368,35 @@ namespace YooAsset
public static RawFileOperation LoadRawFileAsync(string location, string copyPath = null)
{
string assetPath = _locationServices.ConvertLocationToAssetPath(_playMode, location);
return AssetSystem.LoadRawFileAsync(assetPath, copyPath);
if (_playMode == EPlayMode.EditorPlayMode)
{
BundleInfo bundleInfo = new BundleInfo(assetPath);
RawFileOperation operation = new EditorPlayModeRawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else if (_playMode == EPlayMode.OfflinePlayMode)
{
IBundleServices bundleServices = _offlinePlayModeImpl;
string bundleName = bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = bundleServices.GetBundleInfo(bundleName);
RawFileOperation operation = new OfflinePlayModeRawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else if (_playMode == EPlayMode.HostPlayMode)
{
IBundleServices bundleServices = _hostPlayModeImpl;
string bundleName = bundleServices.GetBundleName(assetPath);
BundleInfo bundleInfo = bundleServices.GetBundleInfo(bundleName);
RawFileOperation operation = new HostPlayModeRawFileOperation(bundleInfo, copyPath);
OperationSystem.ProcessOperaiton(operation);
return operation;
}
else
{
throw new NotImplementedException();
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "com.tuyoogame.yooasset",
"displayName": "YooAsset",
"version": "1.0.4",
"version": "1.0.5",
"unity": "2019.4",
"description": "unity3d resources management system",
"author": {

View File

@@ -57,7 +57,7 @@
## 视频教程
Coming soon...
[B站](https://space.bilibili.com/328590743/channel/seriesdetail?sid=2207858)
## 社区