mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-05-15 04:00:16 +00:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
140bcb037f | ||
|
|
2a4384e093 | ||
|
|
5aafed85ed | ||
|
|
6ad4b91c60 | ||
|
|
cd62686316 | ||
|
|
dcd606e573 | ||
|
|
f6f326119c | ||
|
|
f31e5e0d22 | ||
|
|
abc12d2a1d | ||
|
|
b7e2f084b1 | ||
|
|
adf1776b1e | ||
|
|
fd1edcdedf | ||
|
|
ebc25c401d | ||
|
|
67574bf759 | ||
|
|
e94923c3c6 | ||
|
|
5718d57b88 | ||
|
|
82cff36194 | ||
|
|
3e4e2d5eb6 | ||
|
|
015f09d27b | ||
|
|
3fedc5b1b3 | ||
|
|
4776ab9bd8 | ||
|
|
3bb01ef9a8 | ||
|
|
0204f5f68f | ||
|
|
217d88beaa | ||
|
|
77080b3934 | ||
|
|
83f6dc2f76 | ||
|
|
29b3ca4e69 | ||
|
|
9394ff49fd | ||
|
|
49949ecda5 | ||
|
|
1dab0f2b19 | ||
|
|
1cf03bf049 | ||
|
|
c00594738f | ||
|
|
d5f601b0eb | ||
|
|
304bff1f19 | ||
|
|
ce9e0cd88c | ||
|
|
40903d9ad5 | ||
|
|
0fc97ad2f1 | ||
|
|
2bb66ea583 | ||
|
|
03aa9780eb | ||
|
|
d3a9005964 | ||
|
|
48bcf4a848 | ||
|
|
72f0426531 | ||
|
|
44ec5b3de3 | ||
|
|
292fdb1288 | ||
|
|
76e65286fd | ||
|
|
9397a0ebae | ||
|
|
c37b5e52ac | ||
|
|
ecfced7195 | ||
|
|
1c7a79f7d7 | ||
|
|
1149906786 | ||
|
|
9db111c08a | ||
|
|
0844447b46 | ||
|
|
c7116ad165 | ||
|
|
a805e0639e | ||
|
|
e8e69a2e86 | ||
|
|
3e4761a60f | ||
|
|
3413157c67 | ||
|
|
b5f2174ed0 | ||
|
|
bdc8285255 | ||
|
|
cd79f0e434 | ||
|
|
171f40551e |
@@ -2,6 +2,134 @@
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
|
||||
## [1.3.7] - 2022-11-26
|
||||
|
||||
全新的太空战机Demo !
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#45)修复了package列表更新触发的异常。
|
||||
|
||||
### Added
|
||||
|
||||
- 新增了YooAssets.Destroy()资源系统销毁方法。
|
||||
|
||||
```C#
|
||||
/// <summary>
|
||||
/// 销毁资源系统
|
||||
/// </summary>
|
||||
public static void Destroy();
|
||||
```
|
||||
|
||||
### Changed
|
||||
|
||||
- 优化了资源收集规则,原生文件打包名称现在已经包含文件后缀名。
|
||||
- 优化了资源收集规则,非原生文件收集器自动移除Unity无法识别的文件。
|
||||
- 优化了调试信息窗口,列表元素的加载状态显示为文本。
|
||||
|
||||
## [1.3.5] - 2022-11-19
|
||||
|
||||
### Fixed
|
||||
|
||||
- 修复了同步接口加载加密文件失败的问题。
|
||||
|
||||
### Added
|
||||
|
||||
- 新增了方法AssetsPackage.ClearPackageUnusedCacheFilesAsync()
|
||||
|
||||
```c#
|
||||
/// <summary>
|
||||
/// 清理本地包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
public ClearPackageUnusedCacheFilesOperation ClearPackageUnusedCacheFilesAsync()
|
||||
```
|
||||
|
||||
- 新增了方法AssetsPackage.LoadRawFileAsync()
|
||||
|
||||
```c#
|
||||
/// <summary>
|
||||
/// 异步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public RawFileOperationHandle LoadRawFileAsync(string location)
|
||||
```
|
||||
|
||||
- 新增了方法AssetsPackage.LoadRawFileSync()
|
||||
|
||||
```c#
|
||||
/// <summary>
|
||||
/// 同步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public RawFileOperationHandle LoadRawFileSync(string location)
|
||||
```
|
||||
|
||||
### Changed
|
||||
|
||||
- 重命名AssetsPackage.UpdateStaticVersionAsync()为AssetsPackage.UpdatePackageVersionAsync();
|
||||
- 重命名AssetsPackage.UpdateManifestAsync()为AssetsPackage.UpdatePackageManifestAsync();
|
||||
|
||||
### Removed
|
||||
|
||||
- 移除了方法YooAssets.ClearUnusedCacheFiles()
|
||||
- 移除了方法AssetsPackage.GetRawFileAsync()
|
||||
|
||||
## [1.3.4] - 2022-11-04
|
||||
|
||||
### Fixed
|
||||
|
||||
- (#29)修复了EditorHelper中根据guid找uxml有时候会出错的问题。
|
||||
- (#37)修复了在修改GroupName和GroupDesc时,左侧Group栏显示没刷新的问题。
|
||||
- (#38)修复了工程里没有shader的话,SBP构建会报异常的问题。
|
||||
|
||||
### Added
|
||||
|
||||
- 新增了AssetsPackage.CheckPackageContentsAsync()方法
|
||||
|
||||
```c#
|
||||
/// <summary>
|
||||
/// 检查本地包裹内容的完整性
|
||||
/// </summary>
|
||||
public CheckPackageContentsOperation CheckPackageContentsAsync()
|
||||
```
|
||||
|
||||
### Changed
|
||||
|
||||
- 优化了HostPlayMode的初始化逻辑,优先读取沙盒内的清单,如果不存在则读取内置清单。
|
||||
|
||||
- 重写了文件的加密和解密逻辑。
|
||||
|
||||
```c#
|
||||
public interface IDecryptionServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件偏移解密方法
|
||||
/// </summary>
|
||||
ulong LoadFromFileOffset(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件内存解密方法
|
||||
/// </summary>
|
||||
byte[] LoadFromMemory(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件流解密方法
|
||||
/// </summary>
|
||||
System.IO.FileStream LoadFromStream(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件流解密的托管缓存大小
|
||||
/// </summary>
|
||||
uint GetManagedReadBufferSize();
|
||||
}
|
||||
```
|
||||
|
||||
- AssetBundleBuilder界面增加了构建版本选项。
|
||||
|
||||
### Removed
|
||||
|
||||
- 移除了AssetsPackage.WeaklyUpdateManifestAsync()方法。
|
||||
|
||||
## [1.3.3] - 2022-10-27
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace YooAsset.Editor
|
||||
new TaskBuilding(), //开始执行构建
|
||||
new TaskVerifyBuildResult(), //验证构建结果
|
||||
new TaskEncryption(), //加密资源文件
|
||||
new TaskUpdateBuildInfo(), //更新构建信息
|
||||
new TaskCreatePatchManifest(), //创建清单文件
|
||||
new TaskCreateReport(), //创建报告文件
|
||||
new TaskCreatePatchPackage(), //制作补丁包
|
||||
@@ -71,6 +72,7 @@ namespace YooAsset.Editor
|
||||
new TaskBuilding_SBP(), //开始执行构建
|
||||
new TaskVerifyBuildResult_SBP(), //验证构建结果
|
||||
new TaskEncryption(), //加密资源文件
|
||||
new TaskUpdateBuildInfo(), //更新构建信息
|
||||
new TaskCreatePatchManifest(), //创建清单文件
|
||||
new TaskCreateReport(), //创建报告文件
|
||||
new TaskCreatePatchPackage(), //制作补丁包
|
||||
|
||||
@@ -64,27 +64,8 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
public static string MakePipelineOutputDirectory(string outputRoot, string buildPackage, BuildTarget buildTarget, EBuildMode buildMode)
|
||||
{
|
||||
string result = $"{outputRoot}/{buildPackage}/{buildTarget}/{YooAssetSettings.OutputFolderName}";
|
||||
if (buildMode == EBuildMode.DryRunBuild)
|
||||
result += $"_{EBuildMode.DryRunBuild}";
|
||||
else if (buildMode == EBuildMode.SimulateBuild)
|
||||
result += $"_{EBuildMode.SimulateBuild}";
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载补丁清单文件
|
||||
/// </summary>
|
||||
internal static PatchManifest LoadPatchManifestFile(string fileDirectory, string packageName, string packageVersion)
|
||||
{
|
||||
string filePath = $"{fileDirectory}/{YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion)}";
|
||||
if (File.Exists(filePath) == false)
|
||||
{
|
||||
throw new System.Exception($"Not found patch manifest file : {filePath}");
|
||||
}
|
||||
|
||||
string jsonData = FileUtility.ReadFile(filePath);
|
||||
return PatchManifest.Deserialize(jsonData);
|
||||
string outputDirectory = $"{outputRoot}/{buildPackage}/{buildTarget}/{YooAssetSettings.OutputFolderName}";
|
||||
return outputDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ namespace YooAsset.Editor
|
||||
private TextField _buildOutputField;
|
||||
private EnumField _buildPipelineField;
|
||||
private EnumField _buildModeField;
|
||||
private TextField _buildVersionField;
|
||||
private PopupField<string> _buildPackageField;
|
||||
private PopupField<string> _encryptionField;
|
||||
private EnumField _compressionField;
|
||||
@@ -91,6 +92,10 @@ namespace YooAsset.Editor
|
||||
RefreshWindow();
|
||||
});
|
||||
|
||||
// 构建版本
|
||||
_buildVersionField = root.Q<TextField>("BuildVersion");
|
||||
_buildVersionField.SetValueWithoutNotify(GetBuildPackageVersion());
|
||||
|
||||
// 构建包裹
|
||||
var buildPackageContainer = root.Q("BuildPackageContainer");
|
||||
if (_buildPackageNames.Count > 0)
|
||||
@@ -256,7 +261,7 @@ namespace YooAsset.Editor
|
||||
buildParameters.BuildPipeline = AssetBundleBuilderSettingData.Setting.BuildPipeline;
|
||||
buildParameters.BuildMode = AssetBundleBuilderSettingData.Setting.BuildMode;
|
||||
buildParameters.PackageName = AssetBundleBuilderSettingData.Setting.BuildPackage;
|
||||
buildParameters.PackageVersion = GetDefaultPackageVersion();
|
||||
buildParameters.PackageVersion = _buildVersionField.value;
|
||||
buildParameters.VerifyBuildingResult = true;
|
||||
buildParameters.EncryptionServices = CreateEncryptionServicesInstance();
|
||||
buildParameters.CompressOption = AssetBundleBuilderSettingData.Setting.CompressOption;
|
||||
@@ -277,7 +282,9 @@ namespace YooAsset.Editor
|
||||
EditorUtility.RevealInFinder(buildResult.OutputPackageDirectory);
|
||||
}
|
||||
}
|
||||
private string GetDefaultPackageVersion()
|
||||
|
||||
// 构建版本相关
|
||||
private string GetBuildPackageVersion()
|
||||
{
|
||||
int totalMinutes = DateTime.Now.Hour * 60 + DateTime.Now.Minute;
|
||||
return DateTime.Now.ToString("yyyy-MM-dd") + "-" + totalMinutes;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<ui:TextField picking-mode="Ignore" label="Build Output" name="BuildOutput" />
|
||||
<uie:EnumField label="Build Pipeline" name="BuildPipeline" />
|
||||
<uie:EnumField label="Build Mode" name="BuildMode" />
|
||||
<ui:TextField picking-mode="Ignore" label="Build Version" name="BuildVersion" style="width: 350px;" />
|
||||
<ui:VisualElement name="BuildPackageContainer" style="height: 24px;" />
|
||||
<ui:VisualElement name="EncryptionContainer" style="height: 24px;" />
|
||||
<uie:EnumField label="Compression" value="Center" name="Compression" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
@@ -9,6 +10,7 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
public static string SimulateBuild(string packageName)
|
||||
{
|
||||
Debug.Log($"Begin to create simulate package : {packageName}");
|
||||
string defaultOutputRoot = AssetBundleBuilderHelper.GetDefaultOutputRoot();
|
||||
BuildParameters buildParameters = new BuildParameters();
|
||||
buildParameters.OutputRoot = defaultOutputRoot;
|
||||
@@ -21,9 +23,8 @@ namespace YooAsset.Editor
|
||||
var buildResult = builder.Run(buildParameters);
|
||||
if (buildResult.Success)
|
||||
{
|
||||
string pipelineOutputDirectory = AssetBundleBuilderHelper.MakePipelineOutputDirectory(buildParameters.OutputRoot, buildParameters.PackageName, buildParameters.BuildTarget, buildParameters.BuildMode);
|
||||
string manifestFileName = YooAssetSettingsData.GetPatchManifestFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string manifestFilePath = $"{pipelineOutputDirectory}/{manifestFileName}";
|
||||
string manifestFilePath = $"{buildResult.OutputPackageDirectory}/{manifestFileName}";
|
||||
return manifestFilePath;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -8,6 +8,40 @@ namespace YooAsset.Editor
|
||||
{
|
||||
public class BuildBundleInfo
|
||||
{
|
||||
public class BuildPatchInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 构建内容的哈希值
|
||||
/// </summary>
|
||||
public string ContentHash { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值
|
||||
/// </summary>
|
||||
public string PatchFileHash { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值
|
||||
/// </summary>
|
||||
public string PatchFileCRC { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件哈希值
|
||||
/// </summary>
|
||||
public long PatchFileSize { set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构建输出的文件路径
|
||||
/// </summary>
|
||||
public string BuildOutputFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 补丁包输出文件路径
|
||||
/// </summary>
|
||||
public string PatchOutputFilePath { set; get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
@@ -19,6 +53,22 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
public readonly List<BuildAssetInfo> BuildinAssets = new List<BuildAssetInfo>();
|
||||
|
||||
/// <summary>
|
||||
/// 补丁文件信息
|
||||
/// </summary>
|
||||
public readonly BuildPatchInfo PatchInfo = new BuildPatchInfo();
|
||||
|
||||
/// <summary>
|
||||
/// Bundle文件的加载方法
|
||||
/// </summary>
|
||||
public EBundleLoadMethod LoadMethod { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 加密生成文件的路径
|
||||
/// 注意:如果未加密该路径为空
|
||||
/// </summary>
|
||||
public string EncryptedFilePath { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
@@ -36,9 +86,18 @@ namespace YooAsset.Editor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建内容哈希值
|
||||
/// 是否为加密文件
|
||||
/// </summary>
|
||||
public string ContentHash { set; get; } = "00000000000000000000000000000000"; //32位
|
||||
public bool IsEncryptedFile
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(EncryptedFilePath))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BuildBundleInfo(string bundleName)
|
||||
@@ -117,5 +176,20 @@ namespace YooAsset.Editor
|
||||
build.assetNames = GetBuildinAssetPaths();
|
||||
return build;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建PatchBundle类
|
||||
/// </summary>
|
||||
internal PatchBundle CreatePatchBundle()
|
||||
{
|
||||
string fileHash = PatchInfo.PatchFileHash;
|
||||
string fileCRC = PatchInfo.PatchFileCRC;
|
||||
long fileSize = PatchInfo.PatchFileSize;
|
||||
bool isRawFile = IsRawFile;
|
||||
byte loadMethod = (byte)LoadMethod;
|
||||
string[] tags = GetBundleTags();
|
||||
PatchBundle patchBundle = new PatchBundle(BundleName, fileHash, fileCRC, fileSize, isRawFile, loadMethod, tags);
|
||||
return patchBundle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,18 +64,6 @@ namespace YooAsset.Editor
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源包的分类标签列表
|
||||
/// </summary>
|
||||
public string[] GetBundleTags(string bundleName)
|
||||
{
|
||||
if (TryGetBundleInfo(bundleName, out BuildBundleInfo bundleInfo))
|
||||
{
|
||||
return bundleInfo.GetBundleTags();
|
||||
}
|
||||
throw new Exception($"Not found {nameof(BuildBundleInfo)} : {bundleName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取AssetBundle内构建的资源路径列表
|
||||
/// </summary>
|
||||
|
||||
@@ -8,21 +8,6 @@ namespace YooAsset.Editor
|
||||
[Serializable]
|
||||
public class ReportBundleInfo
|
||||
{
|
||||
public class FlagsData
|
||||
{
|
||||
public bool IsEncrypted { private set; get; }
|
||||
public bool IsBuildin { private set; get; }
|
||||
public bool IsRawFile { private set; get; }
|
||||
public FlagsData(bool isEncrypted, bool isBuildin, bool isRawFile)
|
||||
{
|
||||
IsEncrypted = isEncrypted;
|
||||
IsBuildin = isBuildin;
|
||||
IsRawFile = isRawFile;
|
||||
}
|
||||
}
|
||||
|
||||
private FlagsData _flagData;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
@@ -48,33 +33,21 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile;
|
||||
|
||||
/// <summary>
|
||||
/// 加载方法
|
||||
/// </summary>
|
||||
public EBundleLoadMethod LoadMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Tags
|
||||
/// </summary>
|
||||
public string[] Tags;
|
||||
|
||||
/// <summary>
|
||||
/// Flags
|
||||
/// </summary>
|
||||
public int Flags;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取标志位的解析数据
|
||||
/// </summary>
|
||||
public FlagsData GetFlagData()
|
||||
{
|
||||
if (_flagData == null)
|
||||
{
|
||||
BitMask32 value = Flags;
|
||||
bool isEncrypted = value.Test(0);
|
||||
bool isBuildin = value.Test(1);
|
||||
bool isRawFile = value.Test(2);
|
||||
_flagData = new FlagsData(isEncrypted, isBuildin, isRawFile);
|
||||
}
|
||||
return _flagData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源分类标签的字符串
|
||||
/// </summary>
|
||||
@@ -85,16 +58,5 @@ namespace YooAsset.Editor
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile()
|
||||
{
|
||||
if (System.IO.Path.GetExtension(BundleName) == $".{YooAssetSettingsData.Setting.RawFileVariant}")
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,16 +25,19 @@ namespace YooAsset.Editor
|
||||
if (buildMode == EBuildMode.SimulateBuild)
|
||||
return;
|
||||
|
||||
// 开始构建
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
BuildAssetBundleOptions buildOptions = buildParametersContext.GetPipelineBuildOptions();
|
||||
AssetBundleManifest buildResults = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), buildOptions, buildParametersContext.Parameters.BuildTarget);
|
||||
if (buildResults == null)
|
||||
{
|
||||
throw new Exception("构建过程中发生错误!");
|
||||
}
|
||||
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
string unityOutputManifestFilePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/{YooAssetSettings.OutputFolderName}";
|
||||
if(System.IO.File.Exists(unityOutputManifestFilePath) == false)
|
||||
string unityOutputManifestFilePath = $"{pipelineOutputDirectory}/{YooAssetSettings.OutputFolderName}";
|
||||
if (System.IO.File.Exists(unityOutputManifestFilePath) == false)
|
||||
throw new Exception("构建过程中发生严重错误!请查阅上下文日志!");
|
||||
}
|
||||
|
||||
@@ -43,10 +46,10 @@ namespace YooAsset.Editor
|
||||
buildResultContext.UnityManifest = buildResults;
|
||||
context.SetContextObject(buildResultContext);
|
||||
|
||||
// 拷贝原生文件
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
CopyRawBundle(buildMapContext, buildParametersContext);
|
||||
UpdateBuildBundleInfo(buildMapContext, buildParametersContext, buildResultContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,29 +72,5 @@ namespace YooAsset.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新构建结果
|
||||
/// </summary>
|
||||
private void UpdateBuildBundleInfo(BuildMapContext buildMapContext, BuildParametersContext buildParametersContext, BuildResultContext buildResult)
|
||||
{
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
bundleInfo.ContentHash = HashUtility.FileMD5(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
var hash = buildResult.UnityManifest.GetAssetBundleHash(bundleInfo.BundleName);
|
||||
if (hash.isValid)
|
||||
bundleInfo.ContentHash = hash.ToString();
|
||||
else
|
||||
throw new Exception($"Not found bundle in build result : {bundleInfo.BundleName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,10 +46,10 @@ namespace YooAsset.Editor
|
||||
buildResultContext.Results = buildResults;
|
||||
context.SetContextObject(buildResultContext);
|
||||
|
||||
// 拷贝原生文件
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
CopyRawBundle(buildMapContext, buildParametersContext);
|
||||
UpdateBuildBundleInfo(buildMapContext, buildParametersContext, buildResultContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,29 +72,5 @@ namespace YooAsset.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新构建结果
|
||||
/// </summary>
|
||||
private void UpdateBuildBundleInfo(BuildMapContext buildMapContext, BuildParametersContext buildParametersContext, BuildResultContext buildResult)
|
||||
{
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
bundleInfo.ContentHash = HashUtility.FileMD5(filePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 注意:当资源包的依赖列表发生变化的时候,ContentHash也会发生变化!
|
||||
if (buildResult.Results.BundleInfos.TryGetValue(bundleInfo.BundleName, out var value))
|
||||
bundleInfo.ContentHash = value.Hash.ToString();
|
||||
else
|
||||
throw new Exception($"Not found bundle in build result : {bundleInfo.BundleName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,21 @@ namespace YooAsset.Editor
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
if (buildParametersContext.Parameters.CopyBuildinFileOption != ECopyBuildinFileOption.None)
|
||||
var patchManifestContext = context.GetContextObject<PatchManifestContext>();
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
CopyBuildinFilesToStreaming(buildParametersContext);
|
||||
if (buildParametersContext.Parameters.CopyBuildinFileOption != ECopyBuildinFileOption.None)
|
||||
{
|
||||
CopyBuildinFilesToStreaming(buildParametersContext, patchManifestContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拷贝首包资源文件
|
||||
/// </summary>
|
||||
private void CopyBuildinFilesToStreaming(BuildParametersContext buildParametersContext)
|
||||
private void CopyBuildinFilesToStreaming(BuildParametersContext buildParametersContext, PatchManifestContext patchManifestContext)
|
||||
{
|
||||
ECopyBuildinFileOption option = buildParametersContext.Parameters.CopyBuildinFileOption;
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
@@ -30,7 +35,7 @@ namespace YooAsset.Editor
|
||||
string buildPackageVersion = buildParametersContext.Parameters.PackageVersion;
|
||||
|
||||
// 加载补丁清单
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(packageOutputDirectory, buildPackageName, buildPackageVersion);
|
||||
PatchManifest patchManifest = patchManifestContext.Manifest;
|
||||
|
||||
// 清空流目录
|
||||
if (option == ECopyBuildinFileOption.ClearAndCopyAll || option == ECopyBuildinFileOption.ClearAndCopyByTags)
|
||||
|
||||
@@ -8,6 +8,11 @@ using UnityEditor.Build.Pipeline.Interfaces;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class PatchManifestContext : IContextObject
|
||||
{
|
||||
internal PatchManifest Manifest;
|
||||
}
|
||||
|
||||
[TaskAttribute("创建补丁清单文件")]
|
||||
public class TaskCreatePatchManifest : IBuildTask
|
||||
{
|
||||
@@ -24,7 +29,7 @@ namespace YooAsset.Editor
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
|
||||
// 创建新补丁清单
|
||||
PatchManifest patchManifest = new PatchManifest();
|
||||
@@ -45,21 +50,26 @@ namespace YooAsset.Editor
|
||||
UpdateBuiltInBundleReference(patchManifest, buildResultContext.Results);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 创建补丁清单文件
|
||||
string packageHash = string.Empty;
|
||||
string packageHash;
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
PatchManifest.Serialize(filePath, patchManifest);
|
||||
packageHash = HashUtility.FileMD5(filePath);
|
||||
BuildRunner.Log($"创建补丁清单文件:{filePath}");
|
||||
|
||||
var patchManifestContext = new PatchManifestContext();
|
||||
string jsonData = FileUtility.ReadFile(filePath);
|
||||
patchManifestContext.Manifest = PatchManifest.Deserialize(jsonData);
|
||||
context.SetContextObject(patchManifestContext);
|
||||
}
|
||||
|
||||
// 创建补丁清单哈希文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
FileUtility.CreateFile(filePath, packageHash);
|
||||
BuildRunner.Log($"创建补丁清单哈希文件:{filePath}");
|
||||
}
|
||||
@@ -67,7 +77,7 @@ namespace YooAsset.Editor
|
||||
// 创建补丁清单版本文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestVersionFileName(buildParameters.PackageName);
|
||||
string filePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
FileUtility.CreateFile(filePath, buildParameters.PackageVersion);
|
||||
BuildRunner.Log($"创建补丁清单版本文件:{filePath}");
|
||||
}
|
||||
@@ -78,59 +88,17 @@ namespace YooAsset.Editor
|
||||
/// </summary>
|
||||
private List<PatchBundle> GetAllPatchBundle(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var encryptionContext = context.GetContextObject<TaskEncryption.EncryptionContext>();
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
|
||||
List<PatchBundle> result = new List<PatchBundle>(1000);
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
// NOTE:检测路径长度不要超过260字符。
|
||||
string filePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/{bundleInfo.BundleName}";
|
||||
if (filePath.Length >= 260)
|
||||
throw new Exception($"The output bundle name is too long {filePath.Length} chars : {filePath}");
|
||||
|
||||
var bundleName = bundleInfo.BundleName;
|
||||
string fileHash = GetBundleFileHash(bundleInfo, buildParametersContext);
|
||||
string fileCRC = GetBundleFileCRC(bundleInfo, buildParametersContext);
|
||||
long fileSize = GetBundleFileSize(bundleInfo, buildParametersContext);
|
||||
string[] tags = buildMapContext.GetBundleTags(bundleName);
|
||||
bool isEncrypted = encryptionContext.IsEncryptFile(bundleName);
|
||||
bool isRawFile = bundleInfo.IsRawFile;
|
||||
|
||||
PatchBundle patchBundle = new PatchBundle(bundleName, fileHash, fileCRC, fileSize, tags);
|
||||
patchBundle.SetFlagsValue(isRawFile, isEncrypted);
|
||||
var patchBundle = bundleInfo.CreatePatchBundle();
|
||||
result.Add(patchBundle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private string GetBundleFileHash(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000000000000000000000000000"; //32位
|
||||
|
||||
string filePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/{bundleInfo.BundleName}";
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
private string GetBundleFileCRC(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000"; //8位
|
||||
|
||||
string filePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/{bundleInfo.BundleName}";
|
||||
return HashUtility.FileCRC32(filePath);
|
||||
}
|
||||
private long GetBundleFileSize(BuildBundleInfo bundleInfo, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return 0;
|
||||
|
||||
string filePath = $"{buildParametersContext.GetPipelineOutputDirectory()}/{bundleInfo.BundleName}";
|
||||
return FileUtility.GetFileSize(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源列表
|
||||
@@ -200,6 +168,10 @@ namespace YooAsset.Editor
|
||||
shaderBundleReferenceList.Add(valuePair.Key);
|
||||
}
|
||||
|
||||
// 注意:没有任何资源依赖着色器
|
||||
if (shaderBundleReferenceList.Count == 0)
|
||||
return;
|
||||
|
||||
// 获取着色器资源包索引
|
||||
Predicate<PatchBundle> predicate = new Predicate<PatchBundle>(s => s.BundleName == shadersBunldeName);
|
||||
int shaderBundleId = patchManifest.BundleList.FindIndex(predicate);
|
||||
|
||||
@@ -9,55 +9,24 @@ namespace YooAsset.Editor
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var buildMode = buildParameters.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
CopyPatchFiles(buildParameters);
|
||||
CopyPatchFiles(buildParameters, buildMapContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拷贝补丁文件到补丁包目录
|
||||
/// </summary>
|
||||
private void CopyPatchFiles(BuildParametersContext buildParametersContext)
|
||||
private void CopyPatchFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
{
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
BuildRunner.Log($"开始拷贝补丁文件到补丁包目录:{packageOutputDirectory}");
|
||||
|
||||
// 拷贝Report文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string destPath = $"{packageOutputDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string destPath = $"{packageOutputDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单哈希文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string destPath = $"{packageOutputDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
// 拷贝补丁清单版本文件
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestVersionFileName(buildParameters.PackageName);
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string destPath = $"{packageOutputDirectory}/{fileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
|
||||
if (buildParameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
|
||||
{
|
||||
// 拷贝构建日志
|
||||
@@ -75,7 +44,7 @@ namespace YooAsset.Editor
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (buildParameters.BuildPipeline == EBuildPipeline.BuiltinBuildPipeline)
|
||||
{
|
||||
// 拷贝UnityManifest序列化文件
|
||||
{
|
||||
@@ -91,16 +60,17 @@ namespace YooAsset.Editor
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
// 拷贝所有补丁文件
|
||||
int progressValue = 0;
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(pipelineOutputDirectory, buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
int patchFileTotalCount = patchManifest.BundleList.Count;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
int patchFileTotalCount = buildMapContext.BundleInfos.Count;
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
string sourcePath = $"{pipelineOutputDirectory}/{patchBundle.BundleName}";
|
||||
string destPath = $"{packageOutputDirectory}/{patchBundle.FileName}";
|
||||
EditorTools.CopyFile(sourcePath, destPath, true);
|
||||
EditorTools.CopyFile(bundleInfo.PatchInfo.BuildOutputFilePath, bundleInfo.PatchInfo.PatchOutputFilePath, true);
|
||||
EditorTools.DisplayProgressBar("拷贝补丁文件", ++progressValue, patchFileTotalCount);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
@@ -12,24 +12,25 @@ namespace YooAsset.Editor
|
||||
{
|
||||
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
var patchManifestContext = context.GetContextObject<PatchManifestContext>();
|
||||
buildParameters.StopWatch();
|
||||
|
||||
var buildMode = buildParameters.Parameters.BuildMode;
|
||||
if (buildMode != EBuildMode.SimulateBuild)
|
||||
{
|
||||
CreateReportFile(buildParameters, buildMapContext);
|
||||
CreateReportFile(buildParameters, buildMapContext, patchManifestContext);
|
||||
}
|
||||
|
||||
float buildSeconds = buildParameters.GetBuildingSeconds();
|
||||
BuildRunner.Info($"Build time consuming {buildSeconds} seconds.");
|
||||
}
|
||||
|
||||
private void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
private void CreateReportFile(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext, PatchManifestContext patchManifestContext)
|
||||
{
|
||||
var buildParameters = buildParametersContext.Parameters;
|
||||
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
PatchManifest patchManifest = AssetBundleBuilderHelper.LoadPatchManifestFile(pipelineOutputDirectory, buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
PatchManifest patchManifest = patchManifestContext.Manifest;
|
||||
BuildReport buildReport = new BuildReport();
|
||||
|
||||
// 概述信息
|
||||
@@ -49,7 +50,6 @@ namespace YooAsset.Editor
|
||||
buildReport.Summary.BuildPackageVersion = buildParameters.PackageVersion;
|
||||
buildReport.Summary.EnableAddressable = buildMapContext.EnableAddressable;
|
||||
buildReport.Summary.UniqueBundleName = buildMapContext.UniqueBundleName;
|
||||
|
||||
buildReport.Summary.EncryptionServicesClassName = buildParameters.EncryptionServices == null ?
|
||||
"null" : buildParameters.EncryptionServices.GetType().FullName;
|
||||
|
||||
@@ -98,13 +98,14 @@ namespace YooAsset.Editor
|
||||
reportBundleInfo.FileCRC = patchBundle.FileCRC;
|
||||
reportBundleInfo.FileSize = patchBundle.FileSize;
|
||||
reportBundleInfo.Tags = patchBundle.Tags;
|
||||
reportBundleInfo.Flags = patchBundle.Flags;
|
||||
reportBundleInfo.IsRawFile = patchBundle.IsRawFile;
|
||||
reportBundleInfo.LoadMethod = (EBundleLoadMethod)patchBundle.LoadMethod;
|
||||
buildReport.BundleInfos.Add(reportBundleInfo);
|
||||
}
|
||||
|
||||
// 序列化文件
|
||||
string fileName = YooAssetSettingsData.GetReportFileName(buildParameters.PackageName, buildParameters.PackageVersion);
|
||||
string filePath = $"{pipelineOutputDirectory}/{fileName}";
|
||||
string filePath = $"{packageOutputDirectory}/{fileName}";
|
||||
BuildReport.Serialize(filePath, buildReport);
|
||||
BuildRunner.Log($"资源构建报告文件创建完成:{filePath}");
|
||||
}
|
||||
@@ -178,7 +179,7 @@ namespace YooAsset.Editor
|
||||
int fileCount = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsEncrypted)
|
||||
if (patchBundle.LoadMethod != (byte)EBundleLoadMethod.Normal)
|
||||
fileCount++;
|
||||
}
|
||||
return fileCount;
|
||||
@@ -188,7 +189,7 @@ namespace YooAsset.Editor
|
||||
long fileBytes = 0;
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
if (patchBundle.IsEncrypted)
|
||||
if (patchBundle.LoadMethod != (byte)EBundleLoadMethod.Normal)
|
||||
fileBytes += patchBundle.FileSize;
|
||||
}
|
||||
return fileBytes;
|
||||
|
||||
@@ -9,19 +9,6 @@ namespace YooAsset.Editor
|
||||
[TaskAttribute("资源包加密")]
|
||||
public class TaskEncryption : IBuildTask
|
||||
{
|
||||
public class EncryptionContext : IContextObject
|
||||
{
|
||||
public List<string> EncryptList;
|
||||
|
||||
/// <summary>
|
||||
/// 检测是否为加密文件
|
||||
/// </summary>
|
||||
public bool IsEncryptFile(string bundleName)
|
||||
{
|
||||
return EncryptList.Contains(bundleName);
|
||||
}
|
||||
}
|
||||
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParameters = context.GetContextObject<BuildParametersContext>();
|
||||
@@ -30,65 +17,52 @@ namespace YooAsset.Editor
|
||||
var buildMode = buildParameters.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.ForceRebuild || buildMode == EBuildMode.IncrementalBuild)
|
||||
{
|
||||
EncryptionContext encryptionContext = new EncryptionContext();
|
||||
encryptionContext.EncryptList = EncryptFiles(buildParameters, buildMapContext);
|
||||
context.SetContextObject(encryptionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
EncryptionContext encryptionContext = new EncryptionContext();
|
||||
encryptionContext.EncryptList = new List<string>();
|
||||
context.SetContextObject(encryptionContext);
|
||||
EncryptingBundleFiles(buildParameters, buildMapContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加密文件
|
||||
/// </summary>
|
||||
private List<string> EncryptFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
private void EncryptingBundleFiles(BuildParametersContext buildParametersContext, BuildMapContext buildMapContext)
|
||||
{
|
||||
var encryptionServices = buildParametersContext.Parameters.EncryptionServices;
|
||||
|
||||
// 加密资源列表
|
||||
List<string> encryptList = new List<string>();
|
||||
|
||||
// 如果没有设置加密类
|
||||
if (encryptionServices == null)
|
||||
return encryptList;
|
||||
return;
|
||||
|
||||
int progressValue = 0;
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (encryptionServices.Check(bundleInfo.BundleName))
|
||||
bundleInfo.LoadMethod = EBundleLoadMethod.Normal;
|
||||
|
||||
EncryptFileInfo fileInfo = new EncryptFileInfo();
|
||||
fileInfo.BundleName = bundleInfo.BundleName;
|
||||
fileInfo.FilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
|
||||
var encryptResult = encryptionServices.Encrypt(fileInfo);
|
||||
if (encryptResult.LoadMethod != EBundleLoadMethod.Normal)
|
||||
{
|
||||
// 注意:原生文件不支持加密
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"Encryption not support raw file : {bundleInfo.BundleName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
encryptList.Add(bundleInfo.BundleName);
|
||||
|
||||
// 注意:通过判断文件合法性,规避重复加密一个文件
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
byte[] fileData = File.ReadAllBytes(filePath);
|
||||
if (EditorTools.CheckBundleFileValid(fileData))
|
||||
{
|
||||
byte[] bytes = encryptionServices.Encrypt(fileData);
|
||||
File.WriteAllBytes(filePath, bytes);
|
||||
BuildRunner.Log($"文件加密完成:{filePath}");
|
||||
}
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}.encrypt";
|
||||
FileUtility.CreateFile(filePath, encryptResult.EncryptedData);
|
||||
bundleInfo.EncryptedFilePath = filePath;
|
||||
bundleInfo.LoadMethod = encryptResult.LoadMethod;
|
||||
BuildRunner.Log($"Bundle文件加密完成:{filePath}");
|
||||
}
|
||||
|
||||
// 进度条
|
||||
EditorTools.DisplayProgressBar("加密资源包", ++progressValue, buildMapContext.BundleInfos.Count);
|
||||
}
|
||||
EditorTools.ClearProgressBar();
|
||||
|
||||
if(encryptList.Count == 0)
|
||||
UnityEngine.Debug.LogWarning($"没有发现需要加密的文件!");
|
||||
return encryptList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
[TaskAttribute("更新构建信息")]
|
||||
public class TaskUpdateBuildInfo : IBuildTask
|
||||
{
|
||||
void IBuildTask.Run(BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var buildMapContext = context.GetContextObject<BuildMapContext>();
|
||||
string pipelineOutputDirectory = buildParametersContext.GetPipelineOutputDirectory();
|
||||
string packageOutputDirectory = buildParametersContext.GetPackageOutputDirectory();
|
||||
int outputNameStyle = (int)buildParametersContext.Parameters.OutputNameStyle;
|
||||
|
||||
// 1.检测路径长度
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
// NOTE:检测路径长度不要超过260字符。
|
||||
string filePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
if (filePath.Length >= 260)
|
||||
throw new Exception($"The output bundle name is too long {filePath.Length} chars : {filePath}");
|
||||
}
|
||||
|
||||
// 2.更新构建输出的文件路径
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
if (bundleInfo.IsEncryptedFile)
|
||||
bundleInfo.PatchInfo.BuildOutputFilePath = bundleInfo.EncryptedFilePath;
|
||||
else
|
||||
bundleInfo.PatchInfo.BuildOutputFilePath = $"{pipelineOutputDirectory}/{bundleInfo.BundleName}";
|
||||
}
|
||||
|
||||
// 3.更新文件其它信息
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
string buildOutputFilePath = bundleInfo.PatchInfo.BuildOutputFilePath;
|
||||
bundleInfo.PatchInfo.ContentHash = GetBundleContentHash(bundleInfo, context);
|
||||
bundleInfo.PatchInfo.PatchFileHash = GetBundleFileHash(buildOutputFilePath, buildParametersContext);
|
||||
bundleInfo.PatchInfo.PatchFileCRC = GetBundleFileCRC(buildOutputFilePath, buildParametersContext);
|
||||
bundleInfo.PatchInfo.PatchFileSize = GetBundleFileSize(buildOutputFilePath, buildParametersContext);
|
||||
}
|
||||
|
||||
// 4.更新补丁包输出的文件路径
|
||||
foreach (var bundleInfo in buildMapContext.BundleInfos)
|
||||
{
|
||||
string patchFileName = PatchManifest.CreateBundleFileName(outputNameStyle, bundleInfo.BundleName, bundleInfo.PatchInfo.PatchFileHash);
|
||||
bundleInfo.PatchInfo.PatchOutputFilePath = $"{packageOutputDirectory}/{patchFileName}";
|
||||
}
|
||||
}
|
||||
|
||||
private string GetBundleContentHash(BuildBundleInfo bundleInfo, BuildContext context)
|
||||
{
|
||||
var buildParametersContext = context.GetContextObject<BuildParametersContext>();
|
||||
var parameters = buildParametersContext.Parameters;
|
||||
var buildMode = parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000000000000000000000000000"; //32位
|
||||
|
||||
if (bundleInfo.IsRawFile)
|
||||
{
|
||||
string filePath = bundleInfo.PatchInfo.BuildOutputFilePath;
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
|
||||
if (parameters.BuildPipeline == EBuildPipeline.BuiltinBuildPipeline)
|
||||
{
|
||||
var buildResult = context.GetContextObject<TaskBuilding.BuildResultContext>();
|
||||
var hash = buildResult.UnityManifest.GetAssetBundleHash(bundleInfo.BundleName);
|
||||
if (hash.isValid)
|
||||
return hash.ToString();
|
||||
else
|
||||
throw new Exception($"Not found bundle in build result : {bundleInfo.BundleName}");
|
||||
}
|
||||
else if (parameters.BuildPipeline == EBuildPipeline.ScriptableBuildPipeline)
|
||||
{
|
||||
// 注意:当资源包的依赖列表发生变化的时候,ContentHash也会发生变化!
|
||||
var buildResult = context.GetContextObject<TaskBuilding_SBP.BuildResultContext>();
|
||||
if (buildResult.Results.BundleInfos.TryGetValue(bundleInfo.BundleName, out var value))
|
||||
return value.Hash.ToString();
|
||||
else
|
||||
throw new Exception($"Not found bundle in build result : {bundleInfo.BundleName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
private string GetBundleFileHash(string filePath, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000000000000000000000000000"; //32位
|
||||
else
|
||||
return HashUtility.FileMD5(filePath);
|
||||
}
|
||||
private string GetBundleFileCRC(string filePath, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return "00000000"; //8位
|
||||
else
|
||||
return HashUtility.FileCRC32(filePath);
|
||||
}
|
||||
private long GetBundleFileSize(string filePath, BuildParametersContext buildParametersContext)
|
||||
{
|
||||
var buildMode = buildParametersContext.Parameters.BuildMode;
|
||||
if (buildMode == EBuildMode.DryRunBuild || buildMode == EBuildMode.SimulateBuild)
|
||||
return 0;
|
||||
else
|
||||
return FileUtility.GetFileSize(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7382b7d45cb2b73469e37c334a1599d9
|
||||
guid: 4882f54fbf0bcb04680fb581deae4889
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public interface IEncryptionServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测是否需要加密
|
||||
/// </summary>
|
||||
bool Check(string bundleName);
|
||||
|
||||
/// <summary>
|
||||
/// 加密方法
|
||||
/// </summary>
|
||||
/// <param name="fileData">要加密的文件数据</param>
|
||||
/// <returns>返回加密后的字节数据</returns>
|
||||
byte[] Encrypt(byte[] fileData);
|
||||
}
|
||||
}
|
||||
@@ -240,13 +240,15 @@ namespace YooAsset.Editor
|
||||
return false;
|
||||
|
||||
// 忽略Unity无法识别的无效文件
|
||||
/*
|
||||
if (type == typeof(UnityEditor.DefaultAsset))
|
||||
// 注意:只对非原生文件收集器处理
|
||||
if(PackRuleName != nameof(PackRawFile))
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"Cannot pack default asset : {assetPath}");
|
||||
return false;
|
||||
if (type == typeof(UnityEditor.DefaultAsset))
|
||||
{
|
||||
UnityEngine.Debug.LogWarning($"Cannot pack default asset : {assetPath}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
string fileExtension = System.IO.Path.GetExtension(assetPath);
|
||||
if (IsIgnoreFile(fileExtension))
|
||||
|
||||
@@ -187,6 +187,7 @@ namespace YooAsset.Editor
|
||||
{
|
||||
selectGroup.GroupName = evt.newValue;
|
||||
AssetBundleCollectorSettingData.ModifyGroup(selectPackage, selectGroup);
|
||||
FillGroupViewData();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -200,6 +201,7 @@ namespace YooAsset.Editor
|
||||
{
|
||||
selectGroup.GroupDesc = evt.newValue;
|
||||
AssetBundleCollectorSettingData.ModifyGroup(selectPackage, selectGroup);
|
||||
FillGroupViewData();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ namespace YooAsset.Editor
|
||||
/// <summary>
|
||||
/// 以文件路径作为资源包名
|
||||
/// 注意:每个文件独自打资源包
|
||||
/// 例如:收集器路径为 "Assets/UIPanel"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets/uipanel/shop/image/backgroud.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets/uipanel/shop/view/main.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets_uipanel_shop_image_backgroud.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets_uipanel_shop_view_main.bundle"
|
||||
/// </summary>
|
||||
public class PackSeparately : IPackRule
|
||||
{
|
||||
@@ -23,9 +22,8 @@ namespace YooAsset.Editor
|
||||
/// <summary>
|
||||
/// 以父类文件夹路径作为资源包名
|
||||
/// 注意:文件夹下所有文件打进一个资源包
|
||||
/// 例如:收集器路径为 "Assets/UIPanel"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets/uipanel/shop/image.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets/uipanel/shop/view.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets_uipanel_shop_image.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets_uipanel_shop_view.bundle"
|
||||
/// </summary>
|
||||
public class PackDirectory : IPackRule
|
||||
{
|
||||
@@ -42,8 +40,8 @@ namespace YooAsset.Editor
|
||||
/// 以收集器路径下顶级文件夹为资源包名
|
||||
/// 注意:文件夹下所有文件打进一个资源包
|
||||
/// 例如:收集器路径为 "Assets/UIPanel"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets/uipanel/shop.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets/uipanel/shop.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/Image/backgroud.png" --> "assets_uipanel_shop.bundle"
|
||||
/// 例如:"Assets/UIPanel/Shop/View/main.prefab" --> "assets_uipanel_shop.bundle"
|
||||
/// </summary>
|
||||
public class PackTopDirectory : IPackRule
|
||||
{
|
||||
@@ -74,8 +72,17 @@ namespace YooAsset.Editor
|
||||
{
|
||||
string IPackRule.GetBundleName(PackRuleData data)
|
||||
{
|
||||
string bundleName = StringUtility.RemoveExtension(data.CollectPath);
|
||||
return EditorTools.GetRegularPath(bundleName).Replace('/', '_');
|
||||
string collectPath = data.CollectPath;
|
||||
if (AssetDatabase.IsValidFolder(collectPath))
|
||||
{
|
||||
string bundleName = collectPath;
|
||||
return EditorTools.GetRegularPath(bundleName).Replace('/', '_');
|
||||
}
|
||||
else
|
||||
{
|
||||
string bundleName = StringUtility.RemoveExtension(collectPath);
|
||||
return EditorTools.GetRegularPath(bundleName).Replace('/', '_');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +120,8 @@ namespace YooAsset.Editor
|
||||
if (depends.Length != 1)
|
||||
throw new Exception($"{nameof(PackRawFile)} is not support estension : {extension}");
|
||||
|
||||
string bundleName = StringUtility.RemoveExtension(data.AssetPath);
|
||||
return EditorTools.GetRegularPath(bundleName).Replace('/', '_');
|
||||
string bundleName = data.AssetPath;
|
||||
return EditorTools.GetRegularPath(bundleName).Replace('/', '_').Replace('.', '_');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ namespace YooAsset.Editor
|
||||
|
||||
// Status
|
||||
StyleColor textColor;
|
||||
if (providerInfo.Status == (int)ProviderBase.EStatus.Fail)
|
||||
if (providerInfo.Status == ProviderBase.EStatus.Failed.ToString())
|
||||
textColor = new StyleColor(Color.yellow);
|
||||
else
|
||||
textColor = label1.style.color;
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace YooAsset.Editor
|
||||
|
||||
// Status
|
||||
StyleColor textColor;
|
||||
if (bundleInfo.Status == (int)AssetBundleLoaderBase.EStatus.Failed)
|
||||
if (bundleInfo.Status == BundleLoaderBase.EStatus.Failed.ToString())
|
||||
textColor = new StyleColor(Color.yellow);
|
||||
else
|
||||
textColor = label1.style.color;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace YooAsset.Editor
|
||||
private ToolbarButton _topBar1;
|
||||
private ToolbarButton _topBar2;
|
||||
private ToolbarButton _topBar3;
|
||||
private ToolbarButton _topBar4;
|
||||
private ToolbarButton _topBar5;
|
||||
private ToolbarButton _bottomBar1;
|
||||
private ListView _bundleListView;
|
||||
private ListView _includeListView;
|
||||
@@ -53,11 +53,11 @@ namespace YooAsset.Editor
|
||||
_topBar1 = _root.Q<ToolbarButton>("TopBar1");
|
||||
_topBar2 = _root.Q<ToolbarButton>("TopBar2");
|
||||
_topBar3 = _root.Q<ToolbarButton>("TopBar3");
|
||||
_topBar4 = _root.Q<ToolbarButton>("TopBar4");
|
||||
_topBar5 = _root.Q<ToolbarButton>("TopBar5");
|
||||
_topBar1.clicked += TopBar1_clicked;
|
||||
_topBar2.clicked += TopBar2_clicked;
|
||||
_topBar3.clicked += TopBar3_clicked;
|
||||
_topBar4.clicked += TopBar4_clicked;
|
||||
_topBar5.clicked += TopBar4_clicked;
|
||||
|
||||
// 底部按钮栏
|
||||
_bottomBar1 = _root.Q<ToolbarButton>("BottomBar1");
|
||||
@@ -144,7 +144,7 @@ namespace YooAsset.Editor
|
||||
_topBar1.text = $"Bundle Name ({_bundleListView.itemsSource.Count})";
|
||||
_topBar2.text = "Size";
|
||||
_topBar3.text = "Hash";
|
||||
_topBar4.text = "Tags";
|
||||
_topBar5.text = "Tags";
|
||||
|
||||
if (_sortMode == ESortMode.BundleName)
|
||||
{
|
||||
@@ -163,9 +163,9 @@ namespace YooAsset.Editor
|
||||
else if (_sortMode == ESortMode.BundleTags)
|
||||
{
|
||||
if (_descendingSort)
|
||||
_topBar4.text = "Tags ↓";
|
||||
_topBar5.text = "Tags ↓";
|
||||
else
|
||||
_topBar4.text = "Tags ↑";
|
||||
_topBar5.text = "Tags ↑";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -231,6 +231,16 @@ namespace YooAsset.Editor
|
||||
label.name = "Label5";
|
||||
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 = "Label6";
|
||||
label.style.unityTextAlign = TextAnchor.MiddleLeft;
|
||||
label.style.marginLeft = 3f;
|
||||
label.style.flexGrow = 1f;
|
||||
label.style.width = 80;
|
||||
element.Add(label);
|
||||
@@ -255,9 +265,13 @@ namespace YooAsset.Editor
|
||||
var label3 = element.Q<Label>("Label3");
|
||||
label3.text = bundleInfo.FileHash;
|
||||
|
||||
// Tags
|
||||
// LoadMethod
|
||||
var label5 = element.Q<Label>("Label5");
|
||||
label5.text = bundleInfo.GetTagsString();
|
||||
label5.text = bundleInfo.LoadMethod.ToString();
|
||||
|
||||
// Tags
|
||||
var label6 = element.Q<Label>("Label6");
|
||||
label6.text = bundleInfo.GetTagsString();
|
||||
}
|
||||
private void BundleListView_onSelectionChange(IEnumerable<object> objs)
|
||||
{
|
||||
@@ -271,7 +285,7 @@ namespace YooAsset.Editor
|
||||
}
|
||||
private void ShowAssetBundleInspector(ReportBundleInfo bundleInfo)
|
||||
{
|
||||
if (bundleInfo.IsRawFile())
|
||||
if (bundleInfo.IsRawFile)
|
||||
return;
|
||||
|
||||
string rootDirectory = Path.GetDirectoryName(_reportFilePath);
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
<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: 280px; -unity-text-align: middle-left;" />
|
||||
<uie:ToolbarButton text="Tags" display-tooltip-when-elided="true" name="TopBar4" style="width: 80px; -unity-text-align: middle-left; flex-grow: 1;" />
|
||||
<uie:ToolbarButton text="LoadMethod" display-tooltip-when-elided="true" name="TopBar4" style="width: 150px; -unity-text-align: middle-left; flex-grow: 0;" />
|
||||
<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" virtualization-method="DynamicHeight" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
|
||||
@@ -8,7 +8,14 @@ namespace YooAsset.Editor
|
||||
/// <summary>
|
||||
/// 停靠窗口类型集合
|
||||
/// </summary>
|
||||
public static readonly Type[] DockedWindowTypes = { typeof(AssetBundleBuilderWindow), typeof(AssetBundleCollectorWindow), typeof(AssetBundleDebuggerWindow), typeof(AssetBundleReporterWindow)};
|
||||
public static readonly Type[] DockedWindowTypes =
|
||||
{
|
||||
typeof(AssetBundleBuilderWindow),
|
||||
typeof(AssetBundleCollectorWindow),
|
||||
typeof(AssetBundleDebuggerWindow),
|
||||
typeof(AssetBundleReporterWindow),
|
||||
typeof(ShaderVariantCollectorWindow)
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace YooAsset.Editor
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
private readonly static Dictionary<System.Type, string> _uxmlDic = new Dictionary<System.Type, string>();
|
||||
|
||||
/*
|
||||
static EditorHelper()
|
||||
{
|
||||
// 资源包收集
|
||||
@@ -51,6 +52,46 @@ namespace YooAsset.Editor
|
||||
throw new System.Exception($"Invalid YooAsset window type : {windowType}");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 加载窗口的布局文件
|
||||
/// </summary>
|
||||
public static UnityEngine.UIElements.VisualTreeAsset LoadWindowUXML<TWindow>() where TWindow : class
|
||||
{
|
||||
var windowType = typeof(TWindow);
|
||||
|
||||
// 缓存里查询并加载
|
||||
if (_uxmlDic.TryGetValue(windowType, out string uxmlGUID))
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(uxmlGUID);
|
||||
if (string.IsNullOrEmpty(assetPath))
|
||||
{
|
||||
_uxmlDic.Clear();
|
||||
throw new System.Exception($"Invalid UXML GUID : {uxmlGUID} ! Please close the window and open it again !");
|
||||
}
|
||||
var treeAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.UIElements.VisualTreeAsset>(assetPath);
|
||||
return treeAsset;
|
||||
}
|
||||
|
||||
// 全局搜索并加载
|
||||
string[] guids = AssetDatabase.FindAssets(windowType.Name);
|
||||
if (guids.Length == 0)
|
||||
throw new System.Exception($"Not found any assets : {windowType.Name}");
|
||||
|
||||
foreach (string assetGUID in guids)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(assetGUID);
|
||||
var assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
|
||||
if (assetType == typeof(UnityEngine.UIElements.VisualTreeAsset))
|
||||
{
|
||||
_uxmlDic.Add(windowType, assetGUID);
|
||||
var treeAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.UIElements.VisualTreeAsset>(assetPath);
|
||||
return treeAsset;
|
||||
}
|
||||
}
|
||||
throw new System.Exception($"Not found UXML file : {windowType.Name}");
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -349,9 +349,9 @@ namespace YooAsset.Editor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件移动
|
||||
/// 移动文件
|
||||
/// </summary>
|
||||
public static void FileMoveTo(string filePath, string destPath)
|
||||
public static void MoveFile(string filePath, string destPath)
|
||||
{
|
||||
if (File.Exists(destPath))
|
||||
File.Delete(destPath);
|
||||
@@ -359,7 +359,7 @@ namespace YooAsset.Editor
|
||||
FileInfo fileInfo = new FileInfo(filePath);
|
||||
fileInfo.MoveTo(destPath);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 拷贝文件夹
|
||||
/// 注意:包括所有子目录的文件
|
||||
|
||||
@@ -9,7 +9,8 @@ using UnityEditor;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public static class ShaderVariantCollectionReadme
|
||||
[Serializable]
|
||||
public class ShaderVariantCollectionManifest
|
||||
{
|
||||
[Serializable]
|
||||
public class ShaderVariantElement
|
||||
@@ -44,52 +45,49 @@ namespace YooAsset.Editor
|
||||
public List<ShaderVariantElement> ShaderVariantElements = new List<ShaderVariantElement>(1000);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ShaderVariantCollectionManifest
|
||||
|
||||
/// <summary>
|
||||
/// Number of shaders in this collection
|
||||
/// </summary>
|
||||
public int ShaderTotalCount;
|
||||
|
||||
/// <summary>
|
||||
/// Number of total varians in this collection
|
||||
/// </summary>
|
||||
public int VariantTotalCount;
|
||||
|
||||
/// <summary>
|
||||
/// Shader variants info list.
|
||||
/// </summary>
|
||||
public List<ShaderVariantInfo> ShaderVariantInfos = new List<ShaderVariantInfo>(1000);
|
||||
|
||||
/// <summary>
|
||||
/// 添加着色器变种信息
|
||||
/// </summary>
|
||||
public void AddShaderVariant(string assetPath, string shaderName, PassType passType, string[] keywords)
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of shaders in this collection
|
||||
/// </summary>
|
||||
public int ShaderTotalCount;
|
||||
|
||||
/// <summary>
|
||||
/// Number of total varians in this collection
|
||||
/// </summary>
|
||||
public int VariantTotalCount;
|
||||
|
||||
/// <summary>
|
||||
/// Shader variants info list.
|
||||
/// </summary>
|
||||
public List<ShaderVariantInfo> ShaderVariantInfos = new List<ShaderVariantInfo>(1000);
|
||||
|
||||
/// <summary>
|
||||
/// 添加着色器变种信息
|
||||
/// </summary>
|
||||
public void AddShaderVariant(string assetPath, string shaderName, PassType passType, string[] keywords)
|
||||
var info = GetOrCreateShaderVariantInfo(assetPath, shaderName);
|
||||
ShaderVariantElement element = new ShaderVariantElement();
|
||||
element.PassType = passType;
|
||||
element.Keywords = keywords;
|
||||
info.ShaderVariantElements.Add(element);
|
||||
}
|
||||
private ShaderVariantInfo GetOrCreateShaderVariantInfo(string assetPath, string shaderName)
|
||||
{
|
||||
var selectList = ShaderVariantInfos.Where(t => t.ShaderName == shaderName && t.AssetPath == assetPath).ToList();
|
||||
if (selectList.Count == 0)
|
||||
{
|
||||
var info = GetOrCreateShaderVariantInfo(assetPath, shaderName);
|
||||
ShaderVariantElement element = new ShaderVariantElement();
|
||||
element.PassType = passType;
|
||||
element.Keywords = keywords;
|
||||
info.ShaderVariantElements.Add(element);
|
||||
ShaderVariantInfo newInfo = new ShaderVariantInfo();
|
||||
newInfo.AssetPath = assetPath;
|
||||
newInfo.ShaderName = shaderName;
|
||||
ShaderVariantInfos.Add(newInfo);
|
||||
return newInfo;
|
||||
}
|
||||
private ShaderVariantInfo GetOrCreateShaderVariantInfo(string assetPath, string shaderName)
|
||||
{
|
||||
var selectList = ShaderVariantInfos.Where(t => t.ShaderName == shaderName && t.AssetPath == assetPath).ToList();
|
||||
if (selectList.Count == 0)
|
||||
{
|
||||
ShaderVariantInfo newInfo = new ShaderVariantInfo();
|
||||
newInfo.AssetPath = assetPath;
|
||||
newInfo.ShaderName = shaderName;
|
||||
ShaderVariantInfos.Add(newInfo);
|
||||
return newInfo;
|
||||
}
|
||||
|
||||
if (selectList.Count != 1)
|
||||
throw new Exception("Should never get here !");
|
||||
if (selectList.Count != 1)
|
||||
throw new Exception("Should never get here !");
|
||||
|
||||
return selectList[0];
|
||||
}
|
||||
return selectList[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace YooAsset.Editor
|
||||
// 保存结果
|
||||
ShaderVariantCollectionHelper.SaveCurrentShaderVariantCollection(_saveFilePath);
|
||||
|
||||
// 创建说明文件
|
||||
CreateReadme();
|
||||
// 创建清单
|
||||
CreateManifest();
|
||||
|
||||
Debug.Log($"搜集SVC完毕!");
|
||||
_completedCallback?.Invoke();
|
||||
@@ -64,7 +64,7 @@ namespace YooAsset.Editor
|
||||
ShaderVariantCollectionHelper.ClearCurrentShaderVariantCollection();
|
||||
|
||||
// 创建临时测试场景
|
||||
CreateTemperScene();
|
||||
CreateTempScene();
|
||||
|
||||
// 收集着色器变种
|
||||
var materials = GetAllMaterials();
|
||||
@@ -76,9 +76,8 @@ namespace YooAsset.Editor
|
||||
_elapsedTime.Start();
|
||||
}
|
||||
|
||||
private static void CreateTemperScene()
|
||||
private static void CreateTempScene()
|
||||
{
|
||||
// 创建临时场景
|
||||
EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
|
||||
}
|
||||
private static List<Material> GetAllMaterials()
|
||||
@@ -186,17 +185,17 @@ namespace YooAsset.Editor
|
||||
go.transform.position = position;
|
||||
go.name = $"Sphere_{index}|{material.name}";
|
||||
}
|
||||
private static void CreateReadme()
|
||||
private static void CreateManifest()
|
||||
{
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
ShaderVariantCollection svc = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(_saveFilePath);
|
||||
if (svc != null)
|
||||
{
|
||||
var wrapper = ShaderVariantCollectionReadme.Extract(svc);
|
||||
string jsonContents = JsonUtility.ToJson(wrapper, true);
|
||||
string savePath = _saveFilePath.Replace(".shadervariants", "Manifest.json");
|
||||
File.WriteAllText(savePath, jsonContents);
|
||||
var wrapper = ShaderVariantCollectionManifest.Extract(svc);
|
||||
string jsonData = JsonUtility.ToJson(wrapper, true);
|
||||
string savePath = _saveFilePath.Replace(".shadervariants", ".json");
|
||||
File.WriteAllText(savePath, jsonData);
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
|
||||
|
||||
@@ -1,61 +1,82 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_2019_4_OR_NEWER
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace YooAsset.Editor
|
||||
{
|
||||
public class ShaderVariantCollectionWindow : EditorWindow
|
||||
public class ShaderVariantCollectorWindow : EditorWindow
|
||||
{
|
||||
static ShaderVariantCollectionWindow _thisInstance;
|
||||
|
||||
[MenuItem("YooAsset/ShaderVariant Collector", false, 201)]
|
||||
static void ShowWindow()
|
||||
public static void ShowExample()
|
||||
{
|
||||
if (_thisInstance == null)
|
||||
{
|
||||
_thisInstance = GetWindow<ShaderVariantCollectionWindow>("着色器变种收集工具");
|
||||
_thisInstance.minSize = new Vector2(800, 600);
|
||||
}
|
||||
_thisInstance.Show();
|
||||
ShaderVariantCollectorWindow window = GetWindow<ShaderVariantCollectorWindow>("着色器变种收集工具", true, EditorDefine.DockedWindowTypes);
|
||||
window.minSize = new Vector2(800, 600);
|
||||
}
|
||||
|
||||
private ShaderVariantCollection _selectSVC;
|
||||
private Button _collectButton;
|
||||
private TextField _collectOutputField;
|
||||
private Label _currentShaderCountField;
|
||||
private Label _currentVariantCountField;
|
||||
|
||||
private void OnGUI()
|
||||
public void CreateGUI()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
ShaderVariantCollectorSettingData.Setting.SavePath = EditorGUILayout.TextField("收集文件保存路径", ShaderVariantCollectorSettingData.Setting.SavePath);
|
||||
|
||||
int currentShaderCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionShaderCount();
|
||||
int currentVariantCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionVariantCount();
|
||||
EditorGUILayout.LabelField($"CurrentShaderCount : {currentShaderCount}");
|
||||
EditorGUILayout.LabelField($"CurrentVariantCount : {currentVariantCount}");
|
||||
|
||||
// 搜集变种
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("搜集变种", GUILayout.MaxWidth(80)))
|
||||
try
|
||||
{
|
||||
ShaderVariantCollector.Run(ShaderVariantCollectorSettingData.Setting.SavePath, null);
|
||||
}
|
||||
VisualElement root = this.rootVisualElement;
|
||||
|
||||
// 查询
|
||||
EditorGUILayout.Space();
|
||||
if (GUILayout.Button("查询", GUILayout.MaxWidth(80)))
|
||||
{
|
||||
string resultPath = EditorTools.OpenFilePath("Select File", "Assets/", "shadervariants");
|
||||
if (string.IsNullOrEmpty(resultPath))
|
||||
// 加载布局文件
|
||||
var visualAsset = EditorHelper.LoadWindowUXML<ShaderVariantCollectorWindow>();
|
||||
if (visualAsset == null)
|
||||
return;
|
||||
string assetPath = EditorTools.AbsolutePathToAssetPath(resultPath);
|
||||
_selectSVC = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(assetPath);
|
||||
|
||||
visualAsset.CloneTree(root);
|
||||
|
||||
// 文件输出目录
|
||||
_collectOutputField = root.Q<TextField>("CollectOutput");
|
||||
_collectOutputField.SetValueWithoutNotify(ShaderVariantCollectorSettingData.Setting.SavePath);
|
||||
_collectOutputField.RegisterValueChangedCallback(evt =>
|
||||
{
|
||||
ShaderVariantCollectorSettingData.Setting.SavePath = _collectOutputField.value;
|
||||
});
|
||||
|
||||
_currentShaderCountField = root.Q<Label>("CurrentShaderCount");
|
||||
_currentVariantCountField = root.Q<Label>("CurrentVariantCount");
|
||||
|
||||
// 变种收集按钮
|
||||
_collectButton = root.Q<Button>("CollectButton");
|
||||
_collectButton.clicked += CollectButton_clicked;
|
||||
|
||||
//RefreshWindow();
|
||||
}
|
||||
if (_selectSVC != null)
|
||||
catch (Exception e)
|
||||
{
|
||||
EditorGUILayout.LabelField($"ShaderCount : {_selectSVC.shaderCount}");
|
||||
EditorGUILayout.LabelField($"VariantCount : {_selectSVC.variantCount}");
|
||||
Debug.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
private void OnDestroy()
|
||||
private void Update()
|
||||
{
|
||||
ShaderVariantCollectorSettingData.SaveFile();
|
||||
if (_currentShaderCountField != null)
|
||||
{
|
||||
int currentShaderCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionShaderCount();
|
||||
_currentShaderCountField.text = $"Current Shader Count : {currentShaderCount}";
|
||||
}
|
||||
|
||||
if (_currentVariantCountField != null)
|
||||
{
|
||||
int currentVariantCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionVariantCount();
|
||||
_currentVariantCountField.text = $"Current Variant Count : {currentVariantCount}";
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectButton_clicked()
|
||||
{
|
||||
ShaderVariantCollector.Run(ShaderVariantCollectorSettingData.Setting.SavePath, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
<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">
|
||||
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;" />
|
||||
<ui:VisualElement name="BuildContainer">
|
||||
<ui:TextField picking-mode="Ignore" label="文件保存路径" name="CollectOutput" />
|
||||
<ui:Label text="Current Shader Count" display-tooltip-when-elided="true" name="CurrentShaderCount" />
|
||||
<ui:Label text="Current Variant Count" display-tooltip-when-elided="true" name="CurrentVariantCount" />
|
||||
<ui:Button text="开始搜集" display-tooltip-when-elided="true" name="CollectButton" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bff4878063eaf04dab8713e1e662ac5
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -8,13 +8,11 @@ namespace YooAsset
|
||||
{
|
||||
internal class AssetSystemImpl
|
||||
{
|
||||
private static string SceneRunningPackage = string.Empty;
|
||||
|
||||
private readonly List<AssetBundleLoaderBase> _loaders = new List<AssetBundleLoaderBase>(1000);
|
||||
private readonly List<BundleLoaderBase> _loaders = new List<BundleLoaderBase>(1000);
|
||||
private readonly List<ProviderBase> _providers = new List<ProviderBase>(1000);
|
||||
private readonly Dictionary<string, SceneOperationHandle> _sceneHandles = new Dictionary<string, SceneOperationHandle>(100);
|
||||
private readonly static Dictionary<string, SceneOperationHandle> _sceneHandles = new Dictionary<string, SceneOperationHandle>(100);
|
||||
private static long _sceneCreateCount = 0;
|
||||
|
||||
private long _sceneCreateCount = 0;
|
||||
private bool _simulationOnEditor;
|
||||
private int _loadingMaxNumber;
|
||||
public IDecryptionServices DecryptionServices { private set; get; }
|
||||
@@ -71,9 +69,18 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public void DestroyAll()
|
||||
{
|
||||
_loaders.Clear();
|
||||
foreach (var provider in _providers)
|
||||
{
|
||||
provider.Destroy();
|
||||
}
|
||||
foreach (var loader in _loaders)
|
||||
{
|
||||
loader.Destroy(true);
|
||||
}
|
||||
|
||||
_providers.Clear();
|
||||
_sceneHandles.Clear();
|
||||
_loaders.Clear();
|
||||
ClearSceneHandle();
|
||||
|
||||
DecryptionServices = null;
|
||||
BundleServices = null;
|
||||
@@ -83,6 +90,15 @@ namespace YooAsset
|
||||
/// 资源回收(卸载引用计数为零的资源)
|
||||
/// </summary>
|
||||
public void UnloadUnusedAssets()
|
||||
{
|
||||
// 注意:资源包之间可能存在多层深层嵌套,需要多次循环释放。
|
||||
int loopCount = 10;
|
||||
for (int i = 0; i < loopCount; i++)
|
||||
{
|
||||
UnloadUnusedAssetsInternal();
|
||||
}
|
||||
}
|
||||
private void UnloadUnusedAssetsInternal()
|
||||
{
|
||||
if (_simulationOnEditor)
|
||||
{
|
||||
@@ -99,12 +115,12 @@ namespace YooAsset
|
||||
{
|
||||
for (int i = _loaders.Count - 1; i >= 0; i--)
|
||||
{
|
||||
AssetBundleLoaderBase loader = _loaders[i];
|
||||
BundleLoaderBase loader = _loaders[i];
|
||||
loader.TryDestroyAllProviders();
|
||||
}
|
||||
for (int i = _loaders.Count - 1; i >= 0; i--)
|
||||
{
|
||||
AssetBundleLoaderBase loader = _loaders[i];
|
||||
BundleLoaderBase loader = _loaders[i];
|
||||
if (loader.CanDestroy())
|
||||
{
|
||||
loader.Destroy(false);
|
||||
@@ -123,15 +139,14 @@ namespace YooAsset
|
||||
{
|
||||
provider.Destroy();
|
||||
}
|
||||
_providers.Clear();
|
||||
|
||||
foreach (var loader in _loaders)
|
||||
{
|
||||
loader.Destroy(true);
|
||||
}
|
||||
_loaders.Clear();
|
||||
|
||||
_sceneHandles.Clear();
|
||||
_providers.Clear();
|
||||
_loaders.Clear();
|
||||
ClearSceneHandle();
|
||||
|
||||
// 注意:调用底层接口释放所有资源
|
||||
Resources.UnloadUnusedAssets();
|
||||
@@ -144,25 +159,12 @@ namespace YooAsset
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Error($"Failed to load scene. {assetInfo.Error}");
|
||||
YooLogger.Error($"Failed to load scene ! {assetInfo.Error}");
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(assetInfo.Error);
|
||||
return completedProvider.CreateHandle<SceneOperationHandle>();
|
||||
}
|
||||
|
||||
// 注意:场景只允许运行在一个资源包内
|
||||
if (string.IsNullOrEmpty(SceneRunningPackage))
|
||||
{
|
||||
SceneRunningPackage = BundleServices.GetPackageName();
|
||||
}
|
||||
if (BundleServices.GetPackageName() != SceneRunningPackage)
|
||||
{
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
string error = $"Scene are allowed to running within only {SceneRunningPackage}";
|
||||
completedProvider.SetCompleted(error);
|
||||
return completedProvider.CreateHandle<SceneOperationHandle>();
|
||||
}
|
||||
|
||||
// 如果加载的是主场景,则卸载所有缓存的场景
|
||||
if (sceneMode == LoadSceneMode.Single)
|
||||
{
|
||||
@@ -182,6 +184,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
var handle = provider.CreateHandle<SceneOperationHandle>();
|
||||
handle.PackageName = BundleServices.GetPackageName();
|
||||
_sceneHandles.Add(providerGUID, handle);
|
||||
return handle;
|
||||
}
|
||||
@@ -193,7 +196,7 @@ namespace YooAsset
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Error($"Failed to load asset. {assetInfo.Error}");
|
||||
YooLogger.Error($"Failed to load asset ! {assetInfo.Error}");
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(assetInfo.Error);
|
||||
return completedProvider.CreateHandle<AssetOperationHandle>();
|
||||
@@ -220,7 +223,7 @@ namespace YooAsset
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Error($"Failed to load sub assets. {assetInfo.Error}");
|
||||
YooLogger.Error($"Failed to load sub assets ! {assetInfo.Error}");
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(assetInfo.Error);
|
||||
return completedProvider.CreateHandle<SubAssetsOperationHandle>();
|
||||
@@ -240,6 +243,33 @@ namespace YooAsset
|
||||
return provider.CreateHandle<SubAssetsOperationHandle>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载原生文件
|
||||
/// </summary>
|
||||
public RawFileOperationHandle LoadRawFileAsync(AssetInfo assetInfo)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Error($"Failed to load raw file ! {assetInfo.Error}");
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(assetInfo.Error);
|
||||
return completedProvider.CreateHandle<RawFileOperationHandle>();
|
||||
}
|
||||
|
||||
string providerGUID = assetInfo.GUID;
|
||||
ProviderBase provider = TryGetProvider(providerGUID);
|
||||
if (provider == null)
|
||||
{
|
||||
if (_simulationOnEditor)
|
||||
provider = new DatabaseRawFileProvider(this, providerGUID, assetInfo);
|
||||
else
|
||||
provider = new BundledRawFileProvider(this, providerGUID, assetInfo);
|
||||
provider.InitSpawnDebugInfo();
|
||||
_providers.Add(provider);
|
||||
}
|
||||
return provider.CreateHandle<RawFileOperationHandle>();
|
||||
}
|
||||
|
||||
internal void UnloadSubScene(ProviderBase provider)
|
||||
{
|
||||
string providerGUID = provider.ProviderGUID;
|
||||
@@ -265,19 +295,37 @@ namespace YooAsset
|
||||
// 卸载未被使用的资源(包括场景)
|
||||
UnloadUnusedAssets();
|
||||
}
|
||||
internal void ClearSceneHandle()
|
||||
{
|
||||
// 释放资源包下的所有场景
|
||||
string packageName = BundleServices.GetPackageName();
|
||||
List<string> removeList = new List<string>();
|
||||
foreach (var valuePair in _sceneHandles)
|
||||
{
|
||||
if (valuePair.Value.PackageName == packageName)
|
||||
{
|
||||
removeList.Add(valuePair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
internal AssetBundleLoaderBase CreateOwnerAssetBundleLoader(AssetInfo assetInfo)
|
||||
foreach (var key in removeList)
|
||||
{
|
||||
_sceneHandles.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
internal BundleLoaderBase CreateOwnerAssetBundleLoader(AssetInfo assetInfo)
|
||||
{
|
||||
BundleInfo bundleInfo = BundleServices.GetBundleInfo(assetInfo);
|
||||
return CreateAssetBundleLoaderInternal(bundleInfo);
|
||||
}
|
||||
internal List<AssetBundleLoaderBase> CreateDependAssetBundleLoaders(AssetInfo assetInfo)
|
||||
internal List<BundleLoaderBase> CreateDependAssetBundleLoaders(AssetInfo assetInfo)
|
||||
{
|
||||
BundleInfo[] depends = BundleServices.GetAllDependBundleInfos(assetInfo);
|
||||
List<AssetBundleLoaderBase> result = new List<AssetBundleLoaderBase>(depends.Length);
|
||||
List<BundleLoaderBase> result = new List<BundleLoaderBase>(depends.Length);
|
||||
foreach (var bundleInfo in depends)
|
||||
{
|
||||
AssetBundleLoaderBase dependLoader = CreateAssetBundleLoaderInternal(bundleInfo);
|
||||
BundleLoaderBase dependLoader = CreateAssetBundleLoaderInternal(bundleInfo);
|
||||
result.Add(dependLoader);
|
||||
}
|
||||
return result;
|
||||
@@ -290,10 +338,10 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
private AssetBundleLoaderBase CreateAssetBundleLoaderInternal(BundleInfo bundleInfo)
|
||||
private BundleLoaderBase CreateAssetBundleLoaderInternal(BundleInfo bundleInfo)
|
||||
{
|
||||
// 如果加载器已经存在
|
||||
AssetBundleLoaderBase loader = TryGetAssetBundleLoader(bundleInfo.Bundle.BundleName);
|
||||
BundleLoaderBase loader = TryGetAssetBundleLoader(bundleInfo.Bundle.BundleName);
|
||||
if (loader != null)
|
||||
return loader;
|
||||
|
||||
@@ -301,18 +349,21 @@ namespace YooAsset
|
||||
#if UNITY_WEBGL
|
||||
loader = new AssetBundleWebLoader(this, bundleInfo);
|
||||
#else
|
||||
loader = new AssetBundleFileLoader(this, bundleInfo);
|
||||
if (bundleInfo.Bundle.IsRawFile)
|
||||
loader = new RawBundleFileLoader(this, bundleInfo);
|
||||
else
|
||||
loader = new AssetBundleFileLoader(this, bundleInfo);
|
||||
#endif
|
||||
|
||||
_loaders.Add(loader);
|
||||
return loader;
|
||||
}
|
||||
private AssetBundleLoaderBase TryGetAssetBundleLoader(string bundleName)
|
||||
private BundleLoaderBase TryGetAssetBundleLoader(string bundleName)
|
||||
{
|
||||
AssetBundleLoaderBase loader = null;
|
||||
BundleLoaderBase loader = null;
|
||||
for (int i = 0; i < _loaders.Count; i++)
|
||||
{
|
||||
AssetBundleLoaderBase temp = _loaders[i];
|
||||
BundleLoaderBase temp = _loaders[i];
|
||||
if (temp.MainBundleInfo.Bundle.BundleName.Equals(bundleName))
|
||||
{
|
||||
loader = temp;
|
||||
@@ -348,7 +399,7 @@ namespace YooAsset
|
||||
providerInfo.SpawnTime = provider.SpawnTime;
|
||||
providerInfo.LoadingTime = provider.LoadingTime;
|
||||
providerInfo.RefCount = provider.RefCount;
|
||||
providerInfo.Status = (int)provider.Status;
|
||||
providerInfo.Status = provider.Status.ToString();
|
||||
providerInfo.DependBundleInfos = new List<DebugBundleInfo>();
|
||||
result.Add(providerInfo);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace YooAsset
|
||||
{
|
||||
add
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(AssetOperationHandle)} is invalid");
|
||||
if (Provider.IsDone)
|
||||
value.Invoke(this);
|
||||
@@ -31,7 +31,7 @@ namespace YooAsset
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(AssetOperationHandle)} is invalid");
|
||||
_callback -= value;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
return Provider.AssetObject;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ namespace YooAsset
|
||||
/// <typeparam name="TAsset">资源类型</typeparam>
|
||||
public TAsset GetAssetObject<TAsset>() where TAsset : UnityEngine.Object
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
return Provider.AssetObject as TAsset;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return;
|
||||
Provider.WaitForAsyncComplete();
|
||||
}
|
||||
@@ -124,7 +124,7 @@ namespace YooAsset
|
||||
|
||||
private GameObject InstantiateSyncInternal(Vector3 position, Quaternion rotation, Transform parent)
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
if (Provider.AssetObject == null)
|
||||
return null;
|
||||
|
||||
@@ -30,11 +30,11 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return EOperationStatus.None;
|
||||
if (Provider.Status == ProviderBase.EStatus.Fail)
|
||||
if (Provider.Status == ProviderBase.EStatus.Failed)
|
||||
return EOperationStatus.Failed;
|
||||
else if (Provider.Status == ProviderBase.EStatus.Success)
|
||||
else if (Provider.Status == ProviderBase.EStatus.Succeed)
|
||||
return EOperationStatus.Succeed;
|
||||
else
|
||||
return EOperationStatus.None;
|
||||
@@ -48,7 +48,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return string.Empty;
|
||||
return Provider.LastError;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return 0;
|
||||
return Provider.Progress;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return false;
|
||||
return Provider.IsDone;
|
||||
}
|
||||
@@ -84,6 +84,20 @@ namespace YooAsset
|
||||
/// 句柄是否有效
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Provider != null && Provider.IsDestroyed == false)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 句柄是否有效
|
||||
/// </summary>
|
||||
internal bool IsValidWithWarning
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -102,26 +116,12 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 句柄是否有效
|
||||
/// </summary>
|
||||
public bool IsValidNoWarning
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Provider != null && Provider.IsDestroyed == false)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放句柄
|
||||
/// </summary>
|
||||
internal void ReleaseInternal()
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return;
|
||||
Provider.ReleaseHandle(this);
|
||||
Provider = null;
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public class RawFileOperationHandle : OperationHandleBase
|
||||
{
|
||||
private System.Action<RawFileOperationHandle> _callback;
|
||||
|
||||
internal RawFileOperationHandle(ProviderBase provider) : base(provider)
|
||||
{
|
||||
}
|
||||
internal override void InvokeCallback()
|
||||
{
|
||||
_callback?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 完成委托
|
||||
/// </summary>
|
||||
public event System.Action<RawFileOperationHandle> Completed
|
||||
{
|
||||
add
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(RawFileOperationHandle)} is invalid");
|
||||
if (Provider.IsDone)
|
||||
value.Invoke(this);
|
||||
else
|
||||
_callback += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(RawFileOperationHandle)} is invalid");
|
||||
_callback -= value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 等待异步执行完毕
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
return;
|
||||
Provider.WaitForAsyncComplete();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放资源句柄
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
this.ReleaseInternal();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取原生文件的二进制数据
|
||||
/// </summary>
|
||||
public byte[] GetRawFileData()
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
string filePath = Provider.RawFilePath;
|
||||
if (File.Exists(filePath) == false)
|
||||
return null;
|
||||
return File.ReadAllBytes(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取原生文件的文本数据
|
||||
/// </summary>
|
||||
public string GetRawFileText()
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
string filePath = Provider.RawFilePath;
|
||||
if (File.Exists(filePath) == false)
|
||||
return null;
|
||||
return File.ReadAllText(filePath, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取原生文件的路径
|
||||
/// </summary>
|
||||
public string GetRawFilePath()
|
||||
{
|
||||
if (IsValidWithWarning == false)
|
||||
return string.Empty;
|
||||
return Provider.RawFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77a44b35e325fd746b72741d7acf4106
|
||||
guid: e8420ba734d425a4ba9f19173d74503c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -3,8 +3,9 @@
|
||||
namespace YooAsset
|
||||
{
|
||||
public class SceneOperationHandle : OperationHandleBase
|
||||
{
|
||||
{
|
||||
private System.Action<SceneOperationHandle> _callback;
|
||||
internal string PackageName { set; get; }
|
||||
|
||||
internal SceneOperationHandle(ProviderBase provider) : base(provider)
|
||||
{
|
||||
@@ -21,7 +22,7 @@ namespace YooAsset
|
||||
{
|
||||
add
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(SceneOperationHandle)} is invalid");
|
||||
if (Provider.IsDone)
|
||||
value.Invoke(this);
|
||||
@@ -30,7 +31,7 @@ namespace YooAsset
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(SceneOperationHandle)} is invalid");
|
||||
_callback -= value;
|
||||
}
|
||||
@@ -43,7 +44,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return new Scene();
|
||||
return Provider.SceneObject;
|
||||
}
|
||||
@@ -54,7 +55,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public bool ActivateScene()
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return false;
|
||||
|
||||
if (SceneObject.IsValid() && SceneObject.isLoaded)
|
||||
@@ -73,7 +74,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public bool IsMainScene()
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return false;
|
||||
|
||||
if (Provider is DatabaseSceneProvider)
|
||||
@@ -98,7 +99,7 @@ namespace YooAsset
|
||||
public UnloadSceneOperation UnloadAsync()
|
||||
{
|
||||
// 如果句柄无效
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
{
|
||||
string error = $"{nameof(SceneOperationHandle)} is invalid.";
|
||||
var operation = new UnloadSceneOperation(error);
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace YooAsset
|
||||
{
|
||||
add
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(SubAssetsOperationHandle)} is invalid");
|
||||
if (Provider.IsDone)
|
||||
value.Invoke(this);
|
||||
@@ -30,7 +30,7 @@ namespace YooAsset
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
throw new System.Exception($"{nameof(SubAssetsOperationHandle)} is invalid");
|
||||
_callback -= value;
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
return Provider.AllAssetObjects;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public void WaitForAsyncComplete()
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return;
|
||||
Provider.WaitForAsyncComplete();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ namespace YooAsset
|
||||
/// <param name="assetName">子资源对象名称</param>
|
||||
public TObject GetSubAssetObject<TObject>(string assetName) where TObject : UnityEngine.Object
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
|
||||
foreach (var assetObject in Provider.AllAssetObjects)
|
||||
@@ -94,7 +94,7 @@ namespace YooAsset
|
||||
/// <typeparam name="TObject">子资源对象类型</typeparam>
|
||||
public TObject[] GetSubAssetObjects<TObject>() where TObject : UnityEngine.Object
|
||||
{
|
||||
if (IsValid == false)
|
||||
if (IsValidWithWarning == false)
|
||||
return null;
|
||||
|
||||
List<TObject> ret = new List<TObject>(Provider.AllAssetObjects.Length);
|
||||
|
||||
@@ -6,24 +6,27 @@ using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class AssetBundleFileLoader : AssetBundleLoaderBase
|
||||
internal sealed class AssetBundleFileLoader : BundleLoaderBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None = 0,
|
||||
Download,
|
||||
CheckDownload,
|
||||
Unpack,
|
||||
CheckUnpack,
|
||||
LoadFile,
|
||||
CheckLoadFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private string _fileLoadPath;
|
||||
private bool _isWaitForAsyncComplete = false;
|
||||
private bool _isShowWaitForAsyncError = false;
|
||||
private DownloaderBase _unpacker;
|
||||
private DownloaderBase _downloader;
|
||||
private AssetBundleCreateRequest _createRequest;
|
||||
private FileStream _fileStream;
|
||||
|
||||
|
||||
public AssetBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
|
||||
@@ -43,17 +46,31 @@ namespace YooAsset
|
||||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
EBundleLoadMethod loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
|
||||
if (loadMethod == EBundleLoadMethod.LoadFromMemory || loadMethod == EBundleLoadMethod.LoadFromStream)
|
||||
{
|
||||
_steps = ESteps.Unpack;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.LoadFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
}
|
||||
#else
|
||||
_steps = ESteps.LoadFile;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
#endif
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.LoadFile;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -87,47 +104,106 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 加载AssetBundle
|
||||
// 3. 内置文件解压
|
||||
if (_steps == ESteps.Unpack)
|
||||
{
|
||||
int failedTryAgain = 1;
|
||||
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(MainBundleInfo.Bundle);
|
||||
_unpacker = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckUnpack;
|
||||
}
|
||||
|
||||
// 4.检测内置文件解压结果
|
||||
if (_steps == ESteps.CheckUnpack)
|
||||
{
|
||||
if (_unpacker.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_unpacker.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = _unpacker.GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.LoadFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 加载AssetBundle
|
||||
if (_steps == ESteps.LoadFile)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 注意:Unity2017.4编辑器模式下,如果AssetBundle文件不存在会导致编辑器崩溃,这里做了预判。
|
||||
if (System.IO.File.Exists(_fileLoadPath) == false)
|
||||
if (System.IO.File.Exists(FileLoadPath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Not found assetBundle file : {_fileLoadPath}";
|
||||
LastError = $"Not found assetBundle file : {FileLoadPath}";
|
||||
YooLogger.Error(LastError);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Load assetBundle file
|
||||
if (MainBundleInfo.Bundle.IsEncrypted)
|
||||
var loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
|
||||
if (loadMethod == EBundleLoadMethod.Normal)
|
||||
{
|
||||
if (Impl.DecryptionServices == null)
|
||||
throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.Bundle.BundleName}");
|
||||
|
||||
DecryptionFileInfo fileInfo = new DecryptionFileInfo();
|
||||
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
|
||||
fileInfo.FileHash = MainBundleInfo.Bundle.FileHash;
|
||||
ulong offset = Impl.DecryptionServices.GetFileOffset(fileInfo);
|
||||
if (_isWaitForAsyncComplete)
|
||||
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath, 0, offset);
|
||||
CacheBundle = AssetBundle.LoadFromFile(FileLoadPath);
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(FileLoadPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isWaitForAsyncComplete)
|
||||
CacheBundle = AssetBundle.LoadFromFile(_fileLoadPath);
|
||||
if (Impl.DecryptionServices == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"{nameof(IDecryptionServices)} is null : {MainBundleInfo.Bundle.BundleName}";
|
||||
YooLogger.Error(LastError);
|
||||
return;
|
||||
}
|
||||
|
||||
DecryptFileInfo fileInfo = new DecryptFileInfo();
|
||||
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
|
||||
fileInfo.FilePath = FileLoadPath;
|
||||
|
||||
if (loadMethod == EBundleLoadMethod.LoadFromFileOffset)
|
||||
{
|
||||
ulong offset = Impl.DecryptionServices.LoadFromFileOffset(fileInfo);
|
||||
if (_isWaitForAsyncComplete)
|
||||
CacheBundle = AssetBundle.LoadFromFile(FileLoadPath, 0, offset);
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(FileLoadPath, 0, offset);
|
||||
}
|
||||
else if (loadMethod == EBundleLoadMethod.LoadFromMemory)
|
||||
{
|
||||
byte[] fileData = Impl.DecryptionServices.LoadFromMemory(fileInfo);
|
||||
if (_isWaitForAsyncComplete)
|
||||
CacheBundle = AssetBundle.LoadFromMemory(fileData);
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromMemoryAsync(fileData);
|
||||
}
|
||||
else if (loadMethod == EBundleLoadMethod.LoadFromStream)
|
||||
{
|
||||
_fileStream = Impl.DecryptionServices.LoadFromStream(fileInfo);
|
||||
uint managedReadBufferSize = Impl.DecryptionServices.GetManagedReadBufferSize();
|
||||
if (_isWaitForAsyncComplete)
|
||||
CacheBundle = AssetBundle.LoadFromStream(_fileStream, 0, managedReadBufferSize);
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromStreamAsync(_fileStream, 0, managedReadBufferSize);
|
||||
}
|
||||
else
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
_steps = ESteps.CheckLoadFile;
|
||||
}
|
||||
|
||||
// 4. 检测AssetBundle加载结果
|
||||
// 6. 检测AssetBundle加载结果
|
||||
if (_steps == ESteps.CheckLoadFile)
|
||||
{
|
||||
if (_createRequest != null)
|
||||
@@ -177,6 +253,21 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁
|
||||
/// </summary>
|
||||
public override void Destroy(bool forceDestroy)
|
||||
{
|
||||
base.Destroy(forceDestroy);
|
||||
|
||||
if (_fileStream != null)
|
||||
{
|
||||
_fileStream.Close();
|
||||
_fileStream.Dispose();
|
||||
_fileStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主线程等待异步操作完毕
|
||||
/// </summary>
|
||||
@@ -187,6 +278,14 @@ namespace YooAsset
|
||||
int frame = 1000;
|
||||
while (true)
|
||||
{
|
||||
// 文件解压
|
||||
if (_unpacker != null)
|
||||
{
|
||||
_unpacker.Update();
|
||||
if (_unpacker.IsDone() == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
// 保险机制
|
||||
// 注意:如果需要从WEB端下载资源,可能会触发保险机制!
|
||||
frame--;
|
||||
|
||||
@@ -7,7 +7,7 @@ using UnityEngine.Networking;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal sealed class AssetBundleWebLoader : AssetBundleLoaderBase
|
||||
internal sealed class AssetBundleWebLoader : BundleLoaderBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
@@ -17,20 +17,19 @@ namespace YooAsset
|
||||
LoadCacheFile,
|
||||
CheckLoadCacheFile,
|
||||
LoadWebFile,
|
||||
CheckLoadWebFile,
|
||||
CheckLoadWebFile,
|
||||
TryLoadWebFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private float _tryTimer = 0;
|
||||
private string _fileLoadPath;
|
||||
private bool _isShowWaitForAsyncError = false;
|
||||
private DownloaderBase _downloader;
|
||||
private UnityWebRequest _webRequest;
|
||||
private AssetBundleCreateRequest _createRequest;
|
||||
|
||||
|
||||
|
||||
public AssetBundleWebLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
|
||||
{
|
||||
}
|
||||
@@ -48,17 +47,17 @@ namespace YooAsset
|
||||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
_steps = ESteps.LoadWebFile;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.LoadCacheFile;
|
||||
_fileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -97,31 +96,29 @@ namespace YooAsset
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 注意:Unity2017.4编辑器模式下,如果AssetBundle文件不存在会导致编辑器崩溃,这里做了预判。
|
||||
if (System.IO.File.Exists(_fileLoadPath) == false)
|
||||
if (System.IO.File.Exists(FileLoadPath) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Not found assetBundle file : {_fileLoadPath}";
|
||||
LastError = $"Not found assetBundle file : {FileLoadPath}";
|
||||
YooLogger.Error(LastError);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Load assetBundle file
|
||||
if (MainBundleInfo.Bundle.IsEncrypted)
|
||||
var loadMethod = (EBundleLoadMethod)MainBundleInfo.Bundle.LoadMethod;
|
||||
if (loadMethod == EBundleLoadMethod.Normal)
|
||||
{
|
||||
if (Impl.DecryptionServices == null)
|
||||
throw new Exception($"{nameof(AssetBundleFileLoader)} need {nameof(IDecryptionServices)} : {MainBundleInfo.Bundle.BundleName}");
|
||||
|
||||
DecryptionFileInfo fileInfo = new DecryptionFileInfo();
|
||||
fileInfo.BundleName = MainBundleInfo.Bundle.BundleName;
|
||||
fileInfo.FileHash = MainBundleInfo.Bundle.FileHash;
|
||||
ulong offset = Impl.DecryptionServices.GetFileOffset(fileInfo);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath, 0, offset);
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(FileLoadPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
_createRequest = AssetBundle.LoadFromFileAsync(_fileLoadPath);
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"WebGL not support encrypted bundle file : {MainBundleInfo.Bundle.BundleName}";
|
||||
YooLogger.Error(LastError);
|
||||
return;
|
||||
}
|
||||
_steps = ESteps.CheckLoadCacheFile;
|
||||
}
|
||||
@@ -165,7 +162,8 @@ namespace YooAsset
|
||||
// 5. 从WEB网站获取AssetBundle文件
|
||||
if (_steps == ESteps.LoadWebFile)
|
||||
{
|
||||
_webRequest = UnityWebRequestAssetBundle.GetAssetBundle(_fileLoadPath, Hash128.Parse(MainBundleInfo.Bundle.FileHash));
|
||||
var hash = Hash128.Parse(MainBundleInfo.Bundle.FileHash);
|
||||
_webRequest = UnityWebRequestAssetBundle.GetAssetBundle(FileLoadPath, hash);
|
||||
_webRequest.SendWebRequest();
|
||||
_steps = ESteps.CheckLoadWebFile;
|
||||
}
|
||||
@@ -182,7 +180,7 @@ namespace YooAsset
|
||||
if (_webRequest.isNetworkError || _webRequest.isHttpError)
|
||||
#endif
|
||||
{
|
||||
YooLogger.Warning($"Failed to get asset bundle from web : {_fileLoadPath} Error : {_webRequest.error}");
|
||||
YooLogger.Warning($"Failed to get asset bundle from web : {FileLoadPath} Error : {_webRequest.error}");
|
||||
_steps = ESteps.TryLoadWebFile;
|
||||
_tryTimer = 0;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal abstract class AssetBundleLoaderBase
|
||||
internal abstract class BundleLoaderBase
|
||||
{
|
||||
public enum EStatus
|
||||
{
|
||||
@@ -46,9 +46,10 @@ namespace YooAsset
|
||||
|
||||
private readonly List<ProviderBase> _providers = new List<ProviderBase>(100);
|
||||
internal AssetBundle CacheBundle { set; get; }
|
||||
internal string FileLoadPath { set; get; }
|
||||
|
||||
|
||||
|
||||
public AssetBundleLoaderBase(AssetSystemImpl impl, BundleInfo bundleInfo)
|
||||
public BundleLoaderBase(AssetSystemImpl impl, BundleInfo bundleInfo)
|
||||
{
|
||||
Impl = impl;
|
||||
MainBundleInfo = bundleInfo;
|
||||
@@ -89,7 +90,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 销毁
|
||||
/// </summary>
|
||||
public void Destroy(bool forceDestroy)
|
||||
public virtual void Destroy(bool forceDestroy)
|
||||
{
|
||||
IsDestroyed = true;
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 依赖的资源包加载器列表
|
||||
/// </summary>
|
||||
private readonly List<AssetBundleLoaderBase> _dependBundles;
|
||||
private readonly List<BundleLoaderBase> _dependBundles;
|
||||
|
||||
|
||||
public DependAssetBundleGroup(List<AssetBundleLoaderBase> dpendBundles)
|
||||
public DependAssetBundleGroup(List<BundleLoaderBase> dpendBundles)
|
||||
{
|
||||
_dependBundles = dpendBundles;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace YooAsset
|
||||
{
|
||||
foreach (var loader in _dependBundles)
|
||||
{
|
||||
if (loader.Status != AssetBundleLoaderBase.EStatus.Succeed)
|
||||
if (loader.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ namespace YooAsset
|
||||
{
|
||||
foreach (var loader in _dependBundles)
|
||||
{
|
||||
if (loader.Status != AssetBundleLoaderBase.EStatus.Succeed)
|
||||
if (loader.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
return loader.LastError;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace YooAsset
|
||||
var bundleInfo = new DebugBundleInfo();
|
||||
bundleInfo.BundleName = loader.MainBundleInfo.Bundle.BundleName;
|
||||
bundleInfo.RefCount = loader.RefCount;
|
||||
bundleInfo.Status = (int)loader.Status;
|
||||
bundleInfo.Status = loader.Status.ToString();
|
||||
output.Add(bundleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// Bundle文件的加载方法
|
||||
/// </summary>
|
||||
public enum EBundleLoadMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常加载(不需要解密)
|
||||
/// </summary>
|
||||
Normal = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 通过文件偏移来解密加载
|
||||
/// </summary>
|
||||
LoadFromFileOffset = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 通过文件内存来解密加载
|
||||
/// </summary>
|
||||
LoadFromMemory = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 通过文件流来解密加载
|
||||
/// </summary>
|
||||
LoadFromStream = 3,
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64d5737a6f10f8a45b6147e318faa22a
|
||||
guid: 5e32c14ed62806b4189d20ad48ce7631
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,171 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class RawBundleFileLoader : BundleLoaderBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Download,
|
||||
CheckDownload,
|
||||
Unpack,
|
||||
CheckUnpack,
|
||||
CheckFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private bool _isShowWaitForAsyncError = false;
|
||||
private DownloaderBase _unpacker;
|
||||
private DownloaderBase _downloader;
|
||||
|
||||
|
||||
public RawBundleFileLoader(AssetSystemImpl impl, BundleInfo bundleInfo) : base(impl, bundleInfo)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轮询更新
|
||||
/// </summary>
|
||||
public override void Update()
|
||||
{
|
||||
if (_steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.None)
|
||||
{
|
||||
if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.Download;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
#if UNITY_ANDROID || UNITY_WEBGL
|
||||
_steps = ESteps.Unpack;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
#else
|
||||
_steps = ESteps.CheckFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.StreamingFilePath;
|
||||
#endif
|
||||
}
|
||||
else if (MainBundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.CheckFile;
|
||||
FileLoadPath = MainBundleInfo.Bundle.CachedFilePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException(MainBundleInfo.LoadMode.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 下载远端文件
|
||||
if (_steps == ESteps.Download)
|
||||
{
|
||||
int failedTryAgain = int.MaxValue;
|
||||
_downloader = DownloadSystem.BeginDownload(MainBundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 2. 检测下载结果
|
||||
if (_steps == ESteps.CheckDownload)
|
||||
{
|
||||
if (_downloader.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_downloader.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = _downloader.GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 解压内置文件
|
||||
if (_steps == ESteps.Unpack)
|
||||
{
|
||||
int failedTryAgain = 1;
|
||||
var bundleInfo = HostPlayModeImpl.ConvertToUnpackInfo(MainBundleInfo.Bundle);
|
||||
_unpacker = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckUnpack;
|
||||
}
|
||||
|
||||
// 4. 检测解压结果
|
||||
if (_steps == ESteps.CheckUnpack)
|
||||
{
|
||||
if (_unpacker.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_unpacker.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EStatus.Failed;
|
||||
LastError = _unpacker.GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 检测结果
|
||||
if (_steps == ESteps.CheckFile)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
if (File.Exists(FileLoadPath))
|
||||
{
|
||||
Status = EStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Raw file not found : {FileLoadPath}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主线程等待异步操作完毕
|
||||
/// </summary>
|
||||
public override void WaitForAsyncComplete()
|
||||
{
|
||||
int frame = 1000;
|
||||
while (true)
|
||||
{
|
||||
// 文件解压
|
||||
if (_unpacker != null)
|
||||
{
|
||||
_unpacker.Update();
|
||||
if (_unpacker.IsDone() == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
// 保险机制
|
||||
// 注意:如果需要从WEB端下载资源,可能会触发保险机制!
|
||||
frame--;
|
||||
if (frame == 0)
|
||||
{
|
||||
if (_isShowWaitForAsyncError == false)
|
||||
{
|
||||
_isShowWaitForAsyncError = true;
|
||||
YooLogger.Error($"WaitForAsyncComplete failed ! Try load bundle : {MainBundleInfo.Bundle.BundleName} from remote with sync load method !");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 驱动流程
|
||||
Update();
|
||||
|
||||
// 完成后退出
|
||||
if (IsDone())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e26f14db9addb4c49b4f0f520bf75d9d
|
||||
guid: fa39f24727abe514093f18787c0c7e27
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -41,7 +41,7 @@ namespace YooAsset
|
||||
|
||||
if (_steps == ESteps.Clone)
|
||||
{
|
||||
if (_handle.IsValid == false)
|
||||
if (_handle.IsValidWithWarning == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
|
||||
@@ -1,447 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 原生文件操作
|
||||
/// </summary>
|
||||
public abstract class RawFileOperation : AsyncOperationBase
|
||||
{
|
||||
internal readonly BundleInfo _bundleInfo;
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件的拷贝路径
|
||||
/// </summary>
|
||||
public string CopyPath { private set; get; }
|
||||
|
||||
|
||||
internal RawFileOperation(BundleInfo bundleInfo, string copyPath)
|
||||
{
|
||||
_bundleInfo = bundleInfo;
|
||||
CopyPath = copyPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件的缓存路径
|
||||
/// </summary>
|
||||
public abstract string GetCachePath();
|
||||
|
||||
/// <summary>
|
||||
/// 获取原生文件的二进制数据
|
||||
/// </summary>
|
||||
public byte[] LoadFileData()
|
||||
{
|
||||
string filePath = GetCachePath();
|
||||
if (File.Exists(filePath) == false)
|
||||
return null;
|
||||
return File.ReadAllBytes(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取原生文件的文本数据
|
||||
/// </summary>
|
||||
public string LoadFileText()
|
||||
{
|
||||
string filePath = GetCachePath();
|
||||
if (File.Exists(filePath) == false)
|
||||
return string.Empty;
|
||||
return File.ReadAllText(filePath, System.Text.Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发生错误的原生文件操作
|
||||
/// </summary>
|
||||
internal sealed class CompletedRawFileOperation : RawFileOperation
|
||||
{
|
||||
private readonly string _error;
|
||||
internal CompletedRawFileOperation(string error, string copyPath) : base(null, copyPath)
|
||||
{
|
||||
_error = error;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _error;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件的缓存路径
|
||||
/// </summary>
|
||||
public override string GetCachePath()
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.LoadFromEditor)
|
||||
{
|
||||
_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.EditorAssetPath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离线模式的原生文件操作
|
||||
/// </summary>
|
||||
internal sealed class OfflinePlayModeRawFileOperation : RawFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Prepare,
|
||||
DownloadBuildinFile,
|
||||
CheckDownload,
|
||||
CheckAndCopyFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private DownloaderBase _downloader;
|
||||
|
||||
public OfflinePlayModeRawFileOperation(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.Bundle.BundleName}";
|
||||
}
|
||||
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
_steps = ESteps.DownloadBuildinFile;
|
||||
}
|
||||
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.CheckAndCopyFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 下载文件
|
||||
if (_steps == ESteps.DownloadBuildinFile)
|
||||
{
|
||||
int failedTryAgain = int.MaxValue;
|
||||
var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
|
||||
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 3. 检测下载结果
|
||||
if (_steps == ESteps.CheckDownload)
|
||||
{
|
||||
Progress = _downloader.DownloadProgress;
|
||||
if (_downloader.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_downloader.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader.GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckAndCopyFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 检测并拷贝原生文件
|
||||
if (_steps == ESteps.CheckAndCopyFile)
|
||||
{
|
||||
// 如果不需要保存文件
|
||||
if (string.IsNullOrEmpty(CopyPath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果原生文件已经存在,则验证其完整性
|
||||
if (File.Exists(CopyPath))
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_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.Bundle.CachedFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 联机模式的原生文件操作
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeRawFileOperation : RawFileOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
Prepare,
|
||||
DownloadWebFile,
|
||||
DownloadBuildinFile,
|
||||
CheckDownload,
|
||||
CheckAndCopyFile,
|
||||
Done,
|
||||
}
|
||||
|
||||
private ESteps _steps = ESteps.None;
|
||||
private DownloaderBase _downloader;
|
||||
|
||||
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.Bundle.BundleName}";
|
||||
}
|
||||
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromRemote)
|
||||
{
|
||||
_steps = ESteps.DownloadWebFile;
|
||||
}
|
||||
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromStreaming)
|
||||
{
|
||||
_steps = ESteps.DownloadBuildinFile;
|
||||
}
|
||||
else if (_bundleInfo.LoadMode == BundleInfo.ELoadMode.LoadFromCache)
|
||||
{
|
||||
_steps = ESteps.CheckAndCopyFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.NotImplementedException(_bundleInfo.LoadMode.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 下载远端文件
|
||||
if (_steps == ESteps.DownloadWebFile)
|
||||
{
|
||||
int failedTryAgain = int.MaxValue;
|
||||
_downloader = DownloadSystem.BeginDownload(_bundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 3. 下载内置文件
|
||||
if (_steps == ESteps.DownloadBuildinFile)
|
||||
{
|
||||
int failedTryAgain = int.MaxValue;
|
||||
var bundleInfo = PatchHelper.ConvertToUnpackInfo(_bundleInfo.Bundle);
|
||||
_downloader = DownloadSystem.BeginDownload(bundleInfo, failedTryAgain);
|
||||
_steps = ESteps.CheckDownload;
|
||||
}
|
||||
|
||||
// 4. 检测下载结果
|
||||
if (_steps == ESteps.CheckDownload)
|
||||
{
|
||||
Progress = _downloader.DownloadProgress;
|
||||
if (_downloader.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_downloader.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader.GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.CheckAndCopyFile;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 检测并拷贝原生文件
|
||||
if (_steps == ESteps.CheckAndCopyFile)
|
||||
{
|
||||
// 如果不需要保存文件
|
||||
if (string.IsNullOrEmpty(CopyPath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果原生文件已经存在,则验证其完整性
|
||||
if (File.Exists(CopyPath))
|
||||
{
|
||||
var verifyResult = CacheSystem.VerifyContentInternal(CopyPath, _bundleInfo.Bundle.FileSize, _bundleInfo.Bundle.FileCRC, EVerifyLevel.High);
|
||||
if (verifyResult == EVerifyResult.Succeed)
|
||||
{
|
||||
_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.Bundle.CachedFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,15 +48,15 @@ namespace YooAsset
|
||||
|
||||
if (DependBundleGroup.IsSucceed() == false)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = DependBundleGroup.GetLastError();
|
||||
InvokeCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
if (OwnerBundle.Status != AssetBundleLoaderBase.EStatus.Succeed)
|
||||
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = OwnerBundle.LastError;
|
||||
InvokeCompletion();
|
||||
return;
|
||||
@@ -66,7 +66,7 @@ namespace YooAsset
|
||||
{
|
||||
if (OwnerBundle.IsDestroyed)
|
||||
throw new System.Exception("Should never get here !");
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"The bundle {OwnerBundle.MainBundleInfo.Bundle.BundleName} has been destroyed by unity bugs !";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
@@ -115,8 +115,8 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
Status = AssetObject == null ? EStatus.Fail : EStatus.Success;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = AssetObject == null ? EStatus.Failed : EStatus.Succeed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
if (MainAssetInfo.AssetType == null)
|
||||
LastError = $"Failed to load asset : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace YooAsset
|
||||
{
|
||||
internal abstract class BundledProvider : ProviderBase
|
||||
{
|
||||
protected AssetBundleLoaderBase OwnerBundle { private set; get; }
|
||||
protected BundleLoaderBase OwnerBundle { private set; get; }
|
||||
protected DependAssetBundleGroup DependBundleGroup { private set; get; }
|
||||
|
||||
public BundledProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo)
|
||||
@@ -43,7 +43,7 @@ namespace YooAsset
|
||||
var bundleInfo = new DebugBundleInfo();
|
||||
bundleInfo.BundleName = OwnerBundle.MainBundleInfo.Bundle.BundleName;
|
||||
bundleInfo.RefCount = OwnerBundle.RefCount;
|
||||
bundleInfo.Status = (int)OwnerBundle.Status;
|
||||
bundleInfo.Status = OwnerBundle.Status.ToString();
|
||||
output.Add(bundleInfo);
|
||||
|
||||
DependBundleGroup.GetBundleDebugInfos(output);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class BundledRawFileProvider : BundledProvider
|
||||
{
|
||||
public override float Progress
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDone)
|
||||
return 1f;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public BundledRawFileProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo)
|
||||
{
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
DebugRecording();
|
||||
|
||||
if (IsDone)
|
||||
return;
|
||||
|
||||
if (Status == EStatus.None)
|
||||
{
|
||||
Status = EStatus.CheckBundle;
|
||||
}
|
||||
|
||||
if (Status == EStatus.CheckBundle)
|
||||
{
|
||||
if (IsWaitForAsyncComplete)
|
||||
{
|
||||
OwnerBundle.WaitForAsyncComplete();
|
||||
}
|
||||
|
||||
if (OwnerBundle.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
Status = EStatus.Failed;
|
||||
LastError = OwnerBundle.LastError;
|
||||
InvokeCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
Status = EStatus.Checking;
|
||||
}
|
||||
|
||||
if (Status == EStatus.Checking)
|
||||
{
|
||||
RawFilePath = OwnerBundle.FileLoadPath;
|
||||
Status = EStatus.Succeed;
|
||||
InvokeCompletion();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a00889582fd95446b103af1074fa6ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -52,15 +52,15 @@ namespace YooAsset
|
||||
|
||||
if (DependBundleGroup.IsSucceed() == false)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = DependBundleGroup.GetLastError();
|
||||
InvokeCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
if (OwnerBundle.Status != AssetBundleLoaderBase.EStatus.Succeed)
|
||||
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = OwnerBundle.LastError;
|
||||
InvokeCompletion();
|
||||
return;
|
||||
@@ -83,7 +83,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Failed to load scene : {_sceneName}";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
@@ -98,8 +98,8 @@ namespace YooAsset
|
||||
if (SceneObject.IsValid() && _activateOnLoad)
|
||||
SceneManager.SetActiveScene(SceneObject);
|
||||
|
||||
Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = SceneObject.IsValid() ? EStatus.Succeed : EStatus.Failed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
LastError = $"The load scene is invalid : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
|
||||
@@ -48,15 +48,15 @@ namespace YooAsset
|
||||
|
||||
if (DependBundleGroup.IsSucceed() == false)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = DependBundleGroup.GetLastError();
|
||||
InvokeCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
if (OwnerBundle.Status != AssetBundleLoaderBase.EStatus.Succeed)
|
||||
if (OwnerBundle.Status != BundleLoaderBase.EStatus.Succeed)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = OwnerBundle.LastError;
|
||||
InvokeCompletion();
|
||||
return;
|
||||
@@ -104,8 +104,8 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
Status = AllAssetObjects == null ? EStatus.Fail : EStatus.Success;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = AllAssetObjects == null ? EStatus.Failed : EStatus.Succeed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
if (MainAssetInfo.AssetType == null)
|
||||
LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : null AssetBundle : {OwnerBundle.MainBundleInfo.Bundle.BundleName}";
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace YooAsset
|
||||
{
|
||||
if (Status == EStatus.None)
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = error;
|
||||
InvokeCompletion();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace YooAsset
|
||||
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(MainAssetInfo.AssetPath);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Not found asset : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
@@ -59,8 +59,8 @@ namespace YooAsset
|
||||
// 2. 检测加载结果
|
||||
if (Status == EStatus.Checking)
|
||||
{
|
||||
Status = AssetObject == null ? EStatus.Fail : EStatus.Success;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = AssetObject == null ? EStatus.Failed : EStatus.Succeed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
if (MainAssetInfo.AssetType == null)
|
||||
LastError = $"Failed to load asset object : {MainAssetInfo.AssetPath} AssetType : null";
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class DatabaseRawFileProvider : ProviderBase
|
||||
{
|
||||
public override float Progress
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDone)
|
||||
return 1f;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public DatabaseRawFileProvider(AssetSystemImpl impl, string providerGUID, AssetInfo assetInfo) : base(impl, providerGUID, assetInfo)
|
||||
{
|
||||
}
|
||||
public override void Update()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (IsDone)
|
||||
return;
|
||||
|
||||
if (Status == EStatus.None)
|
||||
{
|
||||
// 检测资源文件是否存在
|
||||
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(MainAssetInfo.AssetPath);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Not found asset : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
return;
|
||||
}
|
||||
|
||||
Status = EStatus.Checking;
|
||||
|
||||
// 注意:模拟异步加载效果提前返回
|
||||
if (IsWaitForAsyncComplete == false)
|
||||
return;
|
||||
}
|
||||
|
||||
if(Status == EStatus.Checking)
|
||||
{
|
||||
RawFilePath = MainAssetInfo.AssetPath;
|
||||
Status = EStatus.Succeed;
|
||||
InvokeCompletion();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41d0e9bbc5a3a5b4e8b05d60d40d495a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -51,7 +51,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Failed to load scene : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
@@ -66,8 +66,8 @@ namespace YooAsset
|
||||
if (SceneObject.IsValid() && _activateOnLoad)
|
||||
SceneManager.SetActiveScene(SceneObject);
|
||||
|
||||
Status = SceneObject.IsValid() ? EStatus.Success : EStatus.Fail;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = SceneObject.IsValid() ? EStatus.Succeed : EStatus.Failed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
LastError = $"The loaded scene is invalid : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace YooAsset
|
||||
string guid = UnityEditor.AssetDatabase.AssetPathToGUID(MainAssetInfo.AssetPath);
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
Status = EStatus.Fail;
|
||||
Status = EStatus.Failed;
|
||||
LastError = $"Not found asset : {MainAssetInfo.AssetPath}";
|
||||
YooLogger.Error(LastError);
|
||||
InvokeCompletion();
|
||||
@@ -70,8 +70,8 @@ namespace YooAsset
|
||||
// 2. 检测加载结果
|
||||
if (Status == EStatus.Checking)
|
||||
{
|
||||
Status = AllAssetObjects == null ? EStatus.Fail : EStatus.Success;
|
||||
if (Status == EStatus.Fail)
|
||||
Status = AllAssetObjects == null ? EStatus.Failed : EStatus.Succeed;
|
||||
if (Status == EStatus.Failed)
|
||||
{
|
||||
if (MainAssetInfo.AssetType == null)
|
||||
LastError = $"Failed to load sub assets : {MainAssetInfo.AssetPath} AssetType : null";
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace YooAsset
|
||||
CheckBundle,
|
||||
Loading,
|
||||
Checking,
|
||||
Success,
|
||||
Fail,
|
||||
Succeed,
|
||||
Failed,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,6 +47,11 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public UnityEngine.SceneManagement.Scene SceneObject { protected set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生文件路径
|
||||
/// </summary>
|
||||
public string RawFilePath { protected set; get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 当前的加载状态
|
||||
@@ -75,7 +80,7 @@ namespace YooAsset
|
||||
{
|
||||
get
|
||||
{
|
||||
return Status == EStatus.Success || Status == EStatus.Fail;
|
||||
return Status == EStatus.Succeed || Status == EStatus.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +157,8 @@ namespace YooAsset
|
||||
handle = new SceneOperationHandle(this);
|
||||
else if (typeof(T) == typeof(SubAssetsOperationHandle))
|
||||
handle = new SubAssetsOperationHandle(this);
|
||||
else if (typeof(T) == typeof(RawFileOperationHandle))
|
||||
handle = new RawFileOperationHandle(this);
|
||||
else
|
||||
throw new System.NotImplementedException();
|
||||
|
||||
@@ -216,7 +223,7 @@ namespace YooAsset
|
||||
List<OperationHandleBase> tempers = new List<OperationHandleBase>(_handles);
|
||||
foreach (var hande in tempers)
|
||||
{
|
||||
if (hande.IsValid)
|
||||
if (hande.IsValidWithWarning)
|
||||
{
|
||||
hande.InvokeCallback();
|
||||
}
|
||||
|
||||
@@ -182,27 +182,27 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向网络端请求静态资源版本
|
||||
/// 向网络端请求最新的资源版本
|
||||
/// </summary>
|
||||
/// <param name="timeout">超时时间(默认值:60秒)</param>
|
||||
public UpdateStaticVersionOperation UpdateStaticVersionAsync(int timeout = 60)
|
||||
public UpdatePackageVersionOperation UpdatePackageVersionAsync(int timeout = 60)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdateStaticVersionOperation();
|
||||
var operation = new EditorPlayModeUpdatePackageVersionOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdateStaticVersionOperation();
|
||||
var operation = new OfflinePlayModeUpdatePackageVersionOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
return _hostPlayModeImpl.UpdateStaticVersionAsync(PackageName, timeout);
|
||||
return _hostPlayModeImpl.UpdatePackageVersionAsync(PackageName, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -215,25 +215,25 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="packageVersion">更新的包裹版本</param>
|
||||
/// <param name="timeout">超时时间(默认值:60秒)</param>
|
||||
public UpdateManifestOperation UpdateManifestAsync(string packageVersion, int timeout = 60)
|
||||
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, int timeout = 60)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
DebugCheckUpdateManifest();
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdateManifestOperation();
|
||||
var operation = new EditorPlayModeUpdatePackageManifestOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdateManifestOperation();
|
||||
var operation = new OfflinePlayModeUpdatePackageManifestOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
return _hostPlayModeImpl.UpdatePatchManifestAsync(PackageName, packageVersion, timeout);
|
||||
return _hostPlayModeImpl.UpdatePackageManifestAsync(PackageName, packageVersion, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -242,28 +242,26 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 弱联网情况下加载补丁清单
|
||||
/// 注意:当指定版本内容验证失败后会返回失败。
|
||||
/// 检查本地包裹内容的完整性
|
||||
/// </summary>
|
||||
/// <param name="packageVersion">指定的包裹版本</param>
|
||||
public UpdateManifestOperation WeaklyUpdateManifestAsync(string packageVersion)
|
||||
public CheckPackageContentsOperation CheckPackageContentsAsync()
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdateManifestOperation();
|
||||
var operation = new EditorSimulateModeCheckPackageContentsOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdateManifestOperation();
|
||||
var operation = new OfflinePlayModeCheckPackageContentsOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
return _hostPlayModeImpl.WeaklyUpdatePatchManifestAsync(PackageName, packageVersion);
|
||||
return _hostPlayModeImpl.CheckPackageContentsAsync(PackageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -272,7 +270,18 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取包裹的版本信息
|
||||
/// 清理本地包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
public ClearPackageUnusedCacheFilesOperation ClearPackageUnusedCacheFilesAsync()
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
var operation = new ClearPackageUnusedCacheFilesOperation(this);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本地包裹的版本信息
|
||||
/// </summary>
|
||||
public string GetPackageVersion()
|
||||
{
|
||||
@@ -403,74 +412,63 @@ namespace YooAsset
|
||||
|
||||
#region 原生文件
|
||||
/// <summary>
|
||||
/// 异步获取原生文件
|
||||
/// 同步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
/// <param name="copyPath">拷贝路径</param>
|
||||
public RawFileOperation GetRawFileAsync(string location, string copyPath = null)
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public RawFileOperationHandle LoadRawFileSync(AssetInfo assetInfo)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null);
|
||||
return GetRawFileInternal(assetInfo, copyPath);
|
||||
return LoadRawFileInternal(assetInfo, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取原生文件
|
||||
/// 同步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
/// <param name="copyPath">拷贝路径</param>
|
||||
public RawFileOperation GetRawFileAsync(AssetInfo assetInfo, string copyPath = null)
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public RawFileOperationHandle LoadRawFileSync(string location)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
return GetRawFileInternal(assetInfo, copyPath);
|
||||
AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null);
|
||||
return LoadRawFileInternal(assetInfo, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public RawFileOperationHandle LoadRawFileAsync(AssetInfo assetInfo)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
return LoadRawFileInternal(assetInfo, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public RawFileOperationHandle LoadRawFileAsync(string location)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null);
|
||||
return LoadRawFileInternal(assetInfo, false);
|
||||
}
|
||||
|
||||
|
||||
private RawFileOperation GetRawFileInternal(AssetInfo assetInfo, string copyPath)
|
||||
private RawFileOperationHandle LoadRawFileInternal(AssetInfo assetInfo, bool waitForAsyncComplete)
|
||||
{
|
||||
if (assetInfo.IsInvalid)
|
||||
{
|
||||
YooLogger.Error($"Failed to get raw file. {assetInfo.Error}");
|
||||
RawFileOperation operation = new CompletedRawFileOperation(assetInfo.Error, copyPath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (bundleInfo.Bundle.IsRawFile == false)
|
||||
if (assetInfo.IsInvalid == false)
|
||||
{
|
||||
string error = $"Cannot load asset bundle file using {nameof(GetRawFileAsync)} method !";
|
||||
YooLogger.Error(error);
|
||||
RawFileOperation operation = new CompletedRawFileOperation(error, copyPath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo);
|
||||
if (bundleInfo.Bundle.IsRawFile == false)
|
||||
throw new Exception($"Cannot load asset bundle file using {nameof(LoadRawFileAsync)} method !");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
{
|
||||
RawFileOperation operation = new EditorPlayModeRawFileOperation(bundleInfo, copyPath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
RawFileOperation operation = new OfflinePlayModeRawFileOperation(bundleInfo, copyPath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
RawFileOperation operation = new HostPlayModeRawFileOperation(bundleInfo, copyPath);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
var handle = _assetSystemImpl.LoadRawFileAsync(assetInfo);
|
||||
if (waitForAsyncComplete)
|
||||
handle.WaitForAsyncComplete();
|
||||
return handle;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -583,13 +581,7 @@ namespace YooAsset
|
||||
{
|
||||
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo);
|
||||
if (bundleInfo.Bundle.IsRawFile)
|
||||
{
|
||||
string error = $"Cannot load raw file using LoadAsset method !";
|
||||
YooLogger.Error(error);
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(error);
|
||||
return completedProvider.CreateHandle<AssetOperationHandle>();
|
||||
}
|
||||
throw new Exception($"Cannot load raw file using {nameof(LoadAssetAsync)} method !");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -678,13 +670,7 @@ namespace YooAsset
|
||||
{
|
||||
BundleInfo bundleInfo = _bundleServices.GetBundleInfo(assetInfo);
|
||||
if (bundleInfo.Bundle.IsRawFile)
|
||||
{
|
||||
string error = $"Cannot load raw file using LoadSubAssets method !";
|
||||
YooLogger.Error(error);
|
||||
CompletedProvider completedProvider = new CompletedProvider(assetInfo);
|
||||
completedProvider.SetCompleted(error);
|
||||
return completedProvider.CreateHandle<SubAssetsOperationHandle>();
|
||||
}
|
||||
throw new Exception($"Cannot load raw file using {nameof(LoadSubAssetsAsync)} method !");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -901,24 +887,24 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
/// <param name="packageVersion">指定更新的包裹版本</param>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
public UpdatePackageOperation UpdatePackageAsync(string packageVersion, int timeout = 60)
|
||||
public DownloadPackageOperation DownloadPackageAsync(string packageVersion, int timeout = 60)
|
||||
{
|
||||
DebugCheckInitialize();
|
||||
if (_playMode == EPlayMode.EditorSimulateMode)
|
||||
{
|
||||
var operation = new EditorPlayModeUpdatePackageOperation();
|
||||
var operation = new EditorPlayModeDownloadPackageOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.OfflinePlayMode)
|
||||
{
|
||||
var operation = new OfflinePlayModeUpdatePackageOperation();
|
||||
var operation = new OfflinePlayModeDownloadPackageOperation();
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
else if (_playMode == EPlayMode.HostPlayMode)
|
||||
{
|
||||
return _hostPlayModeImpl.UpdatePackageAsync(PackageName, packageVersion, timeout);
|
||||
return _hostPlayModeImpl.DownloadPackageAsync(PackageName, packageVersion, timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -945,9 +931,9 @@ namespace YooAsset
|
||||
private void DebugCheckInitialize()
|
||||
{
|
||||
if (_initializeStatus == EOperationStatus.None)
|
||||
throw new Exception("YooAssets initialize not completed !");
|
||||
throw new Exception("Package initialize not completed !");
|
||||
else if (_initializeStatus == EOperationStatus.Failed)
|
||||
throw new Exception($"YooAssets initialize failed : {_initializeError}");
|
||||
throw new Exception($"Package initialize failed ! {_initializeError}");
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
@@ -974,7 +960,7 @@ namespace YooAsset
|
||||
var loadedBundleInfos = _assetSystemImpl.GetLoadedBundleInfos();
|
||||
if (loadedBundleInfos.Count > 0)
|
||||
{
|
||||
YooLogger.Warning($"Found loaded bundle before update manifest ! Recommended to call the {nameof(ForceUnloadAllAssets)} method to release loaded bundle !");
|
||||
YooLogger.Error($"Found loaded bundle before update manifest ! Recommended to call the {nameof(ForceUnloadAllAssets)} method to release loaded bundle !");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -30,8 +29,8 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public static bool IsCached(PatchBundle patchBundle)
|
||||
{
|
||||
string fileHash = patchBundle.FileHash;
|
||||
if (_cachedDic.ContainsKey(fileHash))
|
||||
string cacheKey = patchBundle.CacheKey;
|
||||
if (_cachedDic.ContainsKey(cacheKey))
|
||||
{
|
||||
string filePath = patchBundle.CachedFilePath;
|
||||
if (File.Exists(filePath))
|
||||
@@ -40,7 +39,7 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedDic.Remove(fileHash);
|
||||
_cachedDic.Remove(cacheKey);
|
||||
YooLogger.Error($"Cache file is missing : {filePath}");
|
||||
return false;
|
||||
}
|
||||
@@ -56,12 +55,12 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public static void CacheBundle(PatchBundle patchBundle)
|
||||
{
|
||||
string fileHash = patchBundle.FileHash;
|
||||
if (_cachedDic.ContainsKey(fileHash) == false)
|
||||
string cacheKey = patchBundle.CacheKey;
|
||||
if (_cachedDic.ContainsKey(cacheKey) == false)
|
||||
{
|
||||
string filePath = patchBundle.CachedFilePath;
|
||||
YooLogger.Log($"Cache verify file : {filePath}");
|
||||
_cachedDic.Add(fileHash, patchBundle);
|
||||
_cachedDic.Add(cacheKey, patchBundle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 下载文件校验结果
|
||||
/// </summary>
|
||||
public enum EVerifyResult
|
||||
internal enum EVerifyResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件不存在
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 加载状态
|
||||
/// </summary>
|
||||
public int Status;
|
||||
public string Status;
|
||||
|
||||
public int CompareTo(DebugBundleInfo other)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 加载状态
|
||||
/// </summary>
|
||||
public int Status;
|
||||
public string Status;
|
||||
|
||||
/// <summary>
|
||||
/// 依赖的资源包列表
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查本地包裹内容的完整性
|
||||
/// </summary>
|
||||
public abstract class CheckPackageContentsOperation : AsyncOperationBase
|
||||
{
|
||||
}
|
||||
|
||||
internal sealed class EditorSimulateModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
internal EditorSimulateModeCheckPackageContentsOperation()
|
||||
{
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
internal sealed class OfflinePlayModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
internal OfflinePlayModeCheckPackageContentsOperation()
|
||||
{
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
internal sealed class HostPlayModeCheckPackageContentsOperation : CheckPackageContentsOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
CheckLoadedManifest,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly CacheVerifier _cacheVerifier;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private float _verifyTime;
|
||||
|
||||
internal HostPlayModeCheckPackageContentsOperation(HostPlayModeImpl impl, string packageName)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.CheckLoadedManifest;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.CheckLoadedManifest)
|
||||
{
|
||||
if (_impl.LocalPatchManifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Not found loaded package : {_packageName}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList(true);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
|
||||
bool verifySucceed = true;
|
||||
foreach (var verifyInfo in _cacheVerifier.VerifyFailList)
|
||||
{
|
||||
// 注意:跳过内置资源文件
|
||||
if (verifyInfo.IsBuildinFile)
|
||||
continue;
|
||||
|
||||
verifySucceed = false;
|
||||
YooLogger.Warning($"Failed verify file : {verifyInfo.VerifyFilePath}");
|
||||
}
|
||||
|
||||
if (verifySucceed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"The package resource {_packageName} content has verify failed file !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d400b2548d79ca42bec7370f5d66b78
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,9 +5,9 @@ using System.IO;
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 清理未使用的缓存资源操作类
|
||||
/// 清理本地包裹未使用的缓存文件
|
||||
/// </summary>
|
||||
public sealed class ClearUnusedCacheFilesOperation : AsyncOperationBase
|
||||
public sealed class ClearPackageUnusedCacheFilesOperation : AsyncOperationBase
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
@@ -17,14 +17,14 @@ namespace YooAsset
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly List<AssetsPackage> _packages;
|
||||
private readonly AssetsPackage _package;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private List<string> _unusedCacheFilePaths;
|
||||
private int _unusedFileTotalCount = 0;
|
||||
|
||||
internal ClearUnusedCacheFilesOperation(List<AssetsPackage> packages)
|
||||
internal ClearPackageUnusedCacheFilesOperation(AssetsPackage package)
|
||||
{
|
||||
_packages = packages;
|
||||
_package = package;
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
@@ -57,7 +57,7 @@ namespace YooAsset
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
YooLogger.Warning($"Failed delete cache file : {filePath} Exception : {e}");
|
||||
YooLogger.Warning($"Failed delete cache file : {filePath} ! {e.Message}");
|
||||
}
|
||||
}
|
||||
_unusedCacheFilePaths.RemoveAt(i);
|
||||
@@ -84,27 +84,19 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
private List<string> GetUnusedCacheFilePaths()
|
||||
{
|
||||
string cacheFolderPath = SandboxHelper.GetCacheFolderPath();
|
||||
string cacheFolderPath = PersistentHelper.GetCacheFolderPath(_package.PackageName);
|
||||
if (Directory.Exists(cacheFolderPath) == false)
|
||||
return new List<string>();
|
||||
|
||||
// 获取所有缓存文件
|
||||
DirectoryInfo directoryInfo = new DirectoryInfo(cacheFolderPath);
|
||||
FileInfo[] fileInfos = directoryInfo.GetFiles();
|
||||
List<string> result = new List<string>(fileInfos.Length);
|
||||
foreach (FileInfo fileInfo in fileInfos)
|
||||
{
|
||||
bool used = false;
|
||||
foreach (var package in _packages)
|
||||
if (_package.IsIncludeBundleFile(fileInfo.Name) == false)
|
||||
{
|
||||
if (package.IsIncludeBundleFile(fileInfo.Name))
|
||||
{
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (used == false)
|
||||
result.Add(fileInfo.FullName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public abstract class UpdatePackageOperation : AsyncOperationBase
|
||||
public abstract class DownloadPackageOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建包裹下载器
|
||||
@@ -19,7 +19,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 编辑器下模拟运行的更新资源包裹操作
|
||||
/// </summary>
|
||||
internal sealed class EditorPlayModeUpdatePackageOperation : UpdatePackageOperation
|
||||
internal sealed class EditorPlayModeDownloadPackageOperation : DownloadPackageOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
@@ -43,7 +43,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 离线模式的更新资源包裹操作
|
||||
/// </summary>
|
||||
internal sealed class OfflinePlayModeUpdatePackageOperation : UpdatePackageOperation
|
||||
internal sealed class OfflinePlayModeDownloadPackageOperation : DownloadPackageOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 联机模式的更新资源包裹操作
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeUpdatePackageOperation : UpdatePackageOperation
|
||||
internal sealed class HostPlayModeDownloadPackageOperation : DownloadPackageOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
@@ -86,7 +86,7 @@ namespace YooAsset
|
||||
private UnityWebDataRequester _downloader;
|
||||
private PatchManifest _remotePatchManifest;
|
||||
|
||||
internal HostPlayModeUpdatePackageOperation(HostPlayModeImpl impl, string packageName, string packageVersion, int timeout)
|
||||
internal HostPlayModeDownloadPackageOperation(HostPlayModeImpl impl, string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
@@ -128,17 +128,18 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解析补丁清单
|
||||
if (ParseRemotePatchManifest(_downloader.GetText()))
|
||||
// 解析补丁清单
|
||||
try
|
||||
{
|
||||
_remotePatchManifest = PatchManifest.Deserialize(_downloader.GetText());
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
catch(System.Exception e)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"URL : {_downloader.URL} Error : remote patch manifest content is invalid";
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
_downloader.Dispose();
|
||||
@@ -152,13 +153,14 @@ namespace YooAsset
|
||||
{
|
||||
if (Status == EOperationStatus.Succeed)
|
||||
{
|
||||
YooLogger.Log($"Create package downloader : {_remotePatchManifest.PackageName} {_remotePatchManifest.PackageVersion}");
|
||||
List<BundleInfo> downloadList = GetDownloadList();
|
||||
var operation = new PackageDownloaderOperation(downloadList, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Error($"{nameof(UpdatePackageOperation)} status is failed !");
|
||||
YooLogger.Error($"{nameof(DownloadPackageOperation)} status is failed !");
|
||||
var operation = new PackageDownloaderOperation(null, downloadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
}
|
||||
@@ -176,23 +178,6 @@ namespace YooAsset
|
||||
return _impl.GetPatchDownloadMainURL(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析远端请求的补丁清单
|
||||
/// </summary>
|
||||
private bool ParseRemotePatchManifest(string content)
|
||||
{
|
||||
try
|
||||
{
|
||||
_remotePatchManifest = PatchManifest.Deserialize(content);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
YooLogger.Warning(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下载列表
|
||||
/// </summary>
|
||||
@@ -226,6 +226,19 @@ namespace YooAsset
|
||||
{
|
||||
_isPause = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消下载
|
||||
/// </summary>
|
||||
public void CancelDownload()
|
||||
{
|
||||
if (_steps != ESteps.Done)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = "User cancel.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PackageDownloaderOperation : DownloaderOperation
|
||||
|
||||
@@ -10,6 +10,10 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public abstract class InitializationOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化内部加载的包裹版本
|
||||
/// </summary>
|
||||
public string InitializedPackageVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,7 +29,7 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
private readonly EditorSimulateModeImpl _impl;
|
||||
private string _simulatePatchManifestPath;
|
||||
private readonly string _simulatePatchManifestPath;
|
||||
private ESteps _steps = ESteps.None;
|
||||
|
||||
internal EditorSimulateModeInitializationOperation(EditorSimulateModeImpl impl, string simulatePatchManifestPath)
|
||||
@@ -45,16 +49,26 @@ namespace YooAsset
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"Manifest file not found : {_simulatePatchManifestPath}";
|
||||
Error = $"Not found simulation manifest file : {_simulatePatchManifestPath}";
|
||||
return;
|
||||
}
|
||||
|
||||
YooLogger.Log($"Load manifest file : {_simulatePatchManifestPath}");
|
||||
string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath);
|
||||
var simulatePatchManifest = PatchManifest.Deserialize(jsonContent);
|
||||
_impl.SetSimulatePatchManifest(simulatePatchManifest);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
try
|
||||
{
|
||||
YooLogger.Log($"Load simulation manifest file : {_simulatePatchManifestPath}");
|
||||
string jsonContent = FileUtility.ReadFile(_simulatePatchManifestPath);
|
||||
var manifest = PatchManifest.Deserialize(jsonContent);
|
||||
InitializedPackageVersion = manifest.PackageVersion;
|
||||
_impl.SetSimulatePatchManifest(manifest);
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +81,7 @@ namespace YooAsset
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
QueryPackageVersion,
|
||||
QueryAppPackageVersion,
|
||||
LoadAppManifest,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
@@ -76,7 +90,7 @@ namespace YooAsset
|
||||
|
||||
private readonly OfflinePlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly CacheVerifier _patchCacheVerifier;
|
||||
private readonly CacheVerifier _cacheVerifier;
|
||||
private readonly AppPackageVersionQuerier _appPackageVersionQuerier;
|
||||
private AppManifestLoader _appManifestLoader;
|
||||
private ESteps _steps = ESteps.None;
|
||||
@@ -89,21 +103,21 @@ namespace YooAsset
|
||||
_appPackageVersionQuerier = new AppPackageVersionQuerier(packageName);
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_patchCacheVerifier = new CacheVerifierWithoutThread();
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_patchCacheVerifier = new CacheVerifierWithThread();
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.QueryPackageVersion;
|
||||
_steps = ESteps.QueryAppPackageVersion;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.QueryPackageVersion)
|
||||
if (_steps == ESteps.QueryAppPackageVersion)
|
||||
{
|
||||
_appPackageVersionQuerier.Update();
|
||||
if (_appPackageVersionQuerier.IsDone == false)
|
||||
@@ -130,7 +144,8 @@ namespace YooAsset
|
||||
if (_appManifestLoader.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_appManifestLoader.Manifest == null)
|
||||
var manifest = _appManifestLoader.Manifest;
|
||||
if (manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
@@ -138,28 +153,29 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializedPackageVersion = manifest.PackageVersion;
|
||||
_impl.SetAppPatchManifest(manifest);
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
_impl.SetAppPatchManifest(_appManifestLoader.Manifest);
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList();
|
||||
_patchCacheVerifier.InitVerifier(verifyInfos);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _patchCacheVerifier.GetVerifierProgress();
|
||||
if (_patchCacheVerifier.UpdateVerifier())
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessList.Count}, Fail {_patchCacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,15 +183,17 @@ namespace YooAsset
|
||||
|
||||
/// <summary>
|
||||
/// 联机运行模式的初始化操作
|
||||
/// 注意:优先从沙盒里加载清单,如果沙盒里不存在就尝试把内置清单拷贝到沙盒并加载该清单。
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeInitializationOperation : InitializationOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
QueryPackageVersion,
|
||||
LoadAppManifest,
|
||||
TryLoadCacheManifest,
|
||||
QueryAppPackageVersion,
|
||||
CopyAppManifest,
|
||||
LoadAppManifest,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
Done,
|
||||
@@ -183,7 +201,7 @@ namespace YooAsset
|
||||
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly CacheVerifier _patchCacheVerifier;
|
||||
private readonly CacheVerifier _cacheVerifier;
|
||||
private readonly AppPackageVersionQuerier _appPackageVersionQuerier;
|
||||
private AppManifestCopyer _appManifestCopyer;
|
||||
private AppManifestLoader _appManifestLoader;
|
||||
@@ -197,21 +215,46 @@ namespace YooAsset
|
||||
_appPackageVersionQuerier = new AppPackageVersionQuerier(packageName);
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_patchCacheVerifier = new CacheVerifierWithoutThread();
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_patchCacheVerifier = new CacheVerifierWithThread();
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.QueryPackageVersion;
|
||||
_steps = ESteps.TryLoadCacheManifest;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.QueryPackageVersion)
|
||||
if (_steps == ESteps.TryLoadCacheManifest)
|
||||
{
|
||||
if (PersistentHelper.CheckCacheManifestFileExists(_packageName))
|
||||
{
|
||||
try
|
||||
{
|
||||
var manifest = PersistentHelper.LoadCacheManifestFile(_packageName);
|
||||
InitializedPackageVersion = manifest.PackageVersion;
|
||||
_impl.SetLocalPatchManifest(manifest);
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,我们主动把损坏的文件删除。
|
||||
YooLogger.Warning($"Failed to load cache manifest file : {e.Message}");
|
||||
PersistentHelper.DeleteCacheManifestFile(_packageName);
|
||||
_steps = ESteps.QueryAppPackageVersion;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.QueryAppPackageVersion;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.QueryAppPackageVersion)
|
||||
{
|
||||
_appPackageVersionQuerier.Update();
|
||||
if (_appPackageVersionQuerier.IsDone == false)
|
||||
@@ -223,6 +266,7 @@ namespace YooAsset
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
YooLogger.Log($"Failed to load buildin package version file : {error}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -240,7 +284,7 @@ namespace YooAsset
|
||||
return;
|
||||
|
||||
string error = _appManifestCopyer.Error;
|
||||
if(string.IsNullOrEmpty(error) == false)
|
||||
if (string.IsNullOrEmpty(error) == false)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
@@ -259,7 +303,8 @@ namespace YooAsset
|
||||
if (_appManifestLoader.IsDone == false)
|
||||
return;
|
||||
|
||||
if (_appManifestLoader.Manifest == null)
|
||||
var manifest = _appManifestLoader.Manifest;
|
||||
if (manifest == null)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
@@ -267,35 +312,38 @@ namespace YooAsset
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializedPackageVersion = manifest.PackageVersion;
|
||||
_impl.SetLocalPatchManifest(manifest);
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
_impl.SetLocalPatchManifest(_appManifestLoader.Manifest);
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList(false);
|
||||
_patchCacheVerifier.InitVerifier(verifyInfos);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _patchCacheVerifier.GetVerifierProgress();
|
||||
if (_patchCacheVerifier.UpdateVerifier())
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_patchCacheVerifier.VerifySuccessList.Count}, Fail {_patchCacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 内置补丁清单版本查询器
|
||||
/// <summary>
|
||||
/// 内置补丁清单版本查询器
|
||||
/// </summary>
|
||||
internal class AppPackageVersionQuerier
|
||||
{
|
||||
private enum ESteps
|
||||
@@ -367,7 +415,7 @@ namespace YooAsset
|
||||
{
|
||||
Version = _downloader.GetText();
|
||||
if (string.IsNullOrEmpty(Version))
|
||||
Error = $"Buildin package version is empty !";
|
||||
Error = $"Buildin package version file content is empty !";
|
||||
}
|
||||
_steps = ESteps.Done;
|
||||
_downloader.Dispose();
|
||||
@@ -375,7 +423,9 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
// 内置补丁清单加载器
|
||||
/// <summary>
|
||||
/// 内置补丁清单加载器
|
||||
/// </summary>
|
||||
internal class AppManifestLoader
|
||||
{
|
||||
private enum ESteps
|
||||
@@ -461,7 +511,14 @@ namespace YooAsset
|
||||
else
|
||||
{
|
||||
// 解析APP里的补丁清单
|
||||
Manifest = PatchManifest.Deserialize(_downloader.GetText());
|
||||
try
|
||||
{
|
||||
Manifest = PatchManifest.Deserialize(_downloader.GetText());
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
_steps = ESteps.Done;
|
||||
_downloader.Dispose();
|
||||
@@ -469,7 +526,9 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
// 内置补丁清单复制器
|
||||
/// <summary>
|
||||
/// 内置补丁清单复制器
|
||||
/// </summary>
|
||||
internal class AppManifestCopyer
|
||||
{
|
||||
private enum ESteps
|
||||
@@ -530,20 +589,13 @@ namespace YooAsset
|
||||
|
||||
if (_steps == ESteps.CopyAppManifest)
|
||||
{
|
||||
string savePath = PersistentHelper.GetCacheManifestFilePath(_buildinPackageName);
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(_buildinPackageName, _buildinPackageVersion);
|
||||
string destFilePath = PathHelper.MakePersistentLoadPath(fileName);
|
||||
if (File.Exists(destFilePath))
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
}
|
||||
else
|
||||
{
|
||||
string sourceFilePath = PathHelper.MakeStreamingLoadPath(fileName);
|
||||
string url = PathHelper.ConvertToWWWPath(sourceFilePath);
|
||||
_downloader = new UnityWebFileRequester();
|
||||
_downloader.SendRequest(url, destFilePath);
|
||||
_steps = ESteps.CheckAppManifest;
|
||||
}
|
||||
string filePath = PathHelper.MakeStreamingLoadPath(fileName);
|
||||
string url = PathHelper.ConvertToWWWPath(filePath);
|
||||
_downloader = new UnityWebFileRequester();
|
||||
_downloader.SendRequest(url, savePath);
|
||||
_steps = ESteps.CheckAppManifest;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckAppManifest)
|
||||
|
||||
@@ -1,374 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新清单操作
|
||||
/// </summary>
|
||||
public abstract class UpdateManifestOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否发现了新的补丁清单
|
||||
/// </summary>
|
||||
public bool FoundNewManifest { protected set; get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器下模拟运行的更新清单操作
|
||||
/// </summary>
|
||||
internal sealed class EditorPlayModeUpdateManifestOperation : UpdateManifestOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离线模式的更新清单操作
|
||||
/// </summary>
|
||||
internal sealed class OfflinePlayModeUpdateManifestOperation : UpdateManifestOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 联机模式的更新清单操作
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeUpdateManifestOperation : UpdateManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadWebHash,
|
||||
CheckWebHash,
|
||||
LoadWebManifest,
|
||||
CheckWebManifest,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
Done,
|
||||
}
|
||||
|
||||
private static int RequestCount = 0;
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private readonly int _timeout;
|
||||
private UnityWebDataRequester _downloader1;
|
||||
private UnityWebDataRequester _downloader2;
|
||||
private CacheVerifier _cacheVerifier;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private float _verifyTime;
|
||||
|
||||
internal HostPlayModeUpdateManifestOperation(HostPlayModeImpl impl, string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
RequestCount++;
|
||||
_steps = ESteps.LoadWebHash;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadWebHash)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(_packageName, _packageVersion);
|
||||
string webURL = GetPatchManifestRequestURL(fileName);
|
||||
YooLogger.Log($"Beginning to request patch manifest hash : {webURL}");
|
||||
_downloader1 = new UnityWebDataRequester();
|
||||
_downloader1.SendRequest(webURL, _timeout);
|
||||
_steps = ESteps.CheckWebHash;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckWebHash)
|
||||
{
|
||||
if (_downloader1.IsDone() == false)
|
||||
return;
|
||||
|
||||
// Check error
|
||||
if (_downloader1.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader1.GetError();
|
||||
}
|
||||
else
|
||||
{
|
||||
string webManifestHash = _downloader1.GetText();
|
||||
string cachedManifestHash = GetSandboxPatchManifestFileHash(_packageName, _packageVersion);
|
||||
|
||||
// 如果补丁清单文件的哈希值相同
|
||||
if (cachedManifestHash == webManifestHash)
|
||||
{
|
||||
YooLogger.Log($"Patch manifest file hash is not change : {webManifestHash}");
|
||||
LoadSandboxPatchManifest(_packageName, _packageVersion);
|
||||
FoundNewManifest = false;
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Log($"Patch manifest hash is change : {cachedManifestHash} -> {webManifestHash}");
|
||||
FoundNewManifest = true;
|
||||
_steps = ESteps.LoadWebManifest;
|
||||
}
|
||||
}
|
||||
_downloader1.Dispose();
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadWebManifest)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion);
|
||||
string webURL = GetPatchManifestRequestURL(fileName);
|
||||
YooLogger.Log($"Beginning to request patch manifest : {webURL}");
|
||||
_downloader2 = new UnityWebDataRequester();
|
||||
_downloader2.SendRequest(webURL, _timeout);
|
||||
_steps = ESteps.CheckWebManifest;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckWebManifest)
|
||||
{
|
||||
if (_downloader2.IsDone() == false)
|
||||
return;
|
||||
|
||||
// Check error
|
||||
if (_downloader2.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader2.GetError();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 解析补丁清单
|
||||
if (ParseAndSaveRemotePatchManifest(_packageName, _packageVersion, _downloader2.GetText()))
|
||||
{
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"URL : {_downloader2.URL} Error : remote patch manifest content is invalid";
|
||||
}
|
||||
}
|
||||
_downloader2.Dispose();
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList(false);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁清单请求地址
|
||||
/// </summary>
|
||||
private string GetPatchManifestRequestURL(string fileName)
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
if (RequestCount % 2 == 0)
|
||||
return _impl.GetPatchDownloadFallbackURL(fileName);
|
||||
else
|
||||
return _impl.GetPatchDownloadMainURL(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析并保存远端请求的补丁清单
|
||||
/// </summary>
|
||||
private bool ParseAndSaveRemotePatchManifest(string packageName, string packageVersion, string content)
|
||||
{
|
||||
try
|
||||
{
|
||||
var remotePatchManifest = PatchManifest.Deserialize(content);
|
||||
_impl.SetLocalPatchManifest(remotePatchManifest);
|
||||
|
||||
YooLogger.Log("Save remote patch manifest file.");
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
|
||||
string savePath = PathHelper.MakePersistentLoadPath(fileName);
|
||||
PatchManifest.Serialize(savePath, remotePatchManifest);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
YooLogger.Error(e.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载沙盒内的补丁清单
|
||||
/// 注意:在加载本地补丁清单之前,已经验证过文件的哈希值
|
||||
/// </summary>
|
||||
private void LoadSandboxPatchManifest(string packageName, string packageVersion)
|
||||
{
|
||||
YooLogger.Log("Load sandbox patch manifest file.");
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
|
||||
string filePath = PathHelper.MakePersistentLoadPath(fileName);
|
||||
string jsonData = File.ReadAllText(filePath);
|
||||
var sandboxPatchManifest = PatchManifest.Deserialize(jsonData);
|
||||
_impl.SetLocalPatchManifest(sandboxPatchManifest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取沙盒内补丁清单文件的哈希值
|
||||
/// 注意:如果沙盒内补丁清单文件不存在,返回空字符串
|
||||
/// </summary>
|
||||
private string GetSandboxPatchManifestFileHash(string packageName, string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
|
||||
string filePath = PathHelper.MakePersistentLoadPath(fileName);
|
||||
if (File.Exists(filePath))
|
||||
return HashUtility.FileMD5(filePath);
|
||||
else
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 联机模式的更新清单操作(弱联网)
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeWeaklyUpdateManifestOperation : UpdateManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
LoadSandboxManifestHash,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
Done,
|
||||
}
|
||||
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private CacheVerifier _cacheVerifier;
|
||||
private float _verifyTime;
|
||||
|
||||
internal HostPlayModeWeaklyUpdateManifestOperation(HostPlayModeImpl impl, string packageName, string packageVersion)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
_steps = ESteps.LoadSandboxManifestHash;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.LoadSandboxManifestHash)
|
||||
{
|
||||
LoadSandboxPatchManifest(_packageName, _packageVersion);
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList(true);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
|
||||
bool verifySucceed = true;
|
||||
foreach (var verifyInfo in _cacheVerifier.VerifyFailList)
|
||||
{
|
||||
// 注意:跳过内置资源文件
|
||||
if (verifyInfo.IsBuildinFile)
|
||||
continue;
|
||||
|
||||
verifySucceed = false;
|
||||
YooLogger.Warning($"Failed verify file : {verifyInfo.VerifyFilePath}");
|
||||
}
|
||||
|
||||
if (verifySucceed)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = $"The package resource {_packageName}_{_packageVersion} content has verify failed file !";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载沙盒内的补丁清单
|
||||
/// 注意:在加载本地补丁清单之前,未验证过文件的哈希值
|
||||
/// </summary>
|
||||
private void LoadSandboxPatchManifest(string packageName, string packageVersion)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(packageName, packageVersion);
|
||||
string filePath = PathHelper.MakePersistentLoadPath(fileName);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
YooLogger.Log("Load sandbox patch manifest file.");
|
||||
string jsonData = File.ReadAllText(filePath);
|
||||
var sandboxPatchManifest = PatchManifest.Deserialize(jsonData);
|
||||
_impl.SetLocalPatchManifest(sandboxPatchManifest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 向远端请求并更新补丁清单
|
||||
/// </summary>
|
||||
public abstract class UpdatePackageManifestOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否发现了新的补丁清单
|
||||
/// </summary>
|
||||
public bool FoundNewManifest { protected set; get; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器下模拟运行的更新清单操作
|
||||
/// </summary>
|
||||
internal sealed class EditorPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离线模式的更新清单操作
|
||||
/// </summary>
|
||||
internal sealed class OfflinePlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
Status = EOperationStatus.Succeed;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 联机模式的更新清单操作
|
||||
/// 注意:优先比对沙盒清单哈希值,如果有变化就更新远端清单文件,并保存到本地。
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeUpdatePackageManifestOperation : UpdatePackageManifestOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
None,
|
||||
TryLoadCacheHash,
|
||||
LoadWebHash,
|
||||
CheckWebHash,
|
||||
LoadCacheManifest,
|
||||
LoadWebManifest,
|
||||
CheckWebManifest,
|
||||
InitVerifyingCache,
|
||||
UpdateVerifyingCache,
|
||||
Done,
|
||||
}
|
||||
|
||||
private static int RequestCount = 0;
|
||||
private readonly HostPlayModeImpl _impl;
|
||||
private readonly string _packageName;
|
||||
private readonly string _packageVersion;
|
||||
private readonly CacheVerifier _cacheVerifier;
|
||||
private readonly int _timeout;
|
||||
private UnityWebDataRequester _downloader1;
|
||||
private UnityWebDataRequester _downloader2;
|
||||
|
||||
private string _cacheManifestHash;
|
||||
private ESteps _steps = ESteps.None;
|
||||
private float _verifyTime;
|
||||
|
||||
internal HostPlayModeUpdatePackageManifestOperation(HostPlayModeImpl impl, string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
_packageVersion = packageVersion;
|
||||
_timeout = timeout;
|
||||
|
||||
#if UNITY_WEBGL
|
||||
_cacheVerifier = new CacheVerifierWithoutThread();
|
||||
#else
|
||||
_cacheVerifier = new CacheVerifierWithThread();
|
||||
#endif
|
||||
}
|
||||
internal override void Start()
|
||||
{
|
||||
RequestCount++;
|
||||
_steps = ESteps.TryLoadCacheHash;
|
||||
}
|
||||
internal override void Update()
|
||||
{
|
||||
if (_steps == ESteps.None || _steps == ESteps.Done)
|
||||
return;
|
||||
|
||||
if (_steps == ESteps.TryLoadCacheHash)
|
||||
{
|
||||
string filePath = PersistentHelper.GetCacheManifestFilePath(_packageName);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
_cacheManifestHash = HashUtility.FileMD5(filePath);
|
||||
_steps = ESteps.LoadWebHash;
|
||||
}
|
||||
else
|
||||
{
|
||||
_steps = ESteps.LoadWebManifest;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadWebHash)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestHashFileName(_packageName, _packageVersion);
|
||||
string webURL = GetPatchManifestRequestURL(fileName);
|
||||
YooLogger.Log($"Beginning to request patch manifest hash : {webURL}");
|
||||
_downloader1 = new UnityWebDataRequester();
|
||||
_downloader1.SendRequest(webURL, _timeout);
|
||||
_steps = ESteps.CheckWebHash;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckWebHash)
|
||||
{
|
||||
if (_downloader1.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_downloader1.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader1.GetError();
|
||||
}
|
||||
else
|
||||
{
|
||||
string webManifestHash = _downloader1.GetText();
|
||||
if (_cacheManifestHash == webManifestHash)
|
||||
{
|
||||
YooLogger.Log($"Not found new package : {_packageName}");
|
||||
_steps = ESteps.LoadCacheManifest;
|
||||
}
|
||||
else
|
||||
{
|
||||
YooLogger.Log($"Package {_packageName} is change : {_cacheManifestHash} -> {webManifestHash}");
|
||||
_steps = ESteps.LoadWebManifest;
|
||||
}
|
||||
}
|
||||
_downloader1.Dispose();
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadCacheManifest)
|
||||
{
|
||||
try
|
||||
{
|
||||
var manifest = PersistentHelper.LoadCacheManifestFile(_packageName);
|
||||
_impl.SetLocalPatchManifest(manifest);
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
// 注意:如果加载沙盒内的清单报错,为了避免流程被卡住,我们主动把损坏的文件删除。
|
||||
YooLogger.Warning($"Failed to load cache manifest file : {e.Message}");
|
||||
PersistentHelper.DeleteCacheManifestFile(_packageName);
|
||||
_steps = ESteps.LoadWebManifest;
|
||||
}
|
||||
}
|
||||
|
||||
if (_steps == ESteps.LoadWebManifest)
|
||||
{
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileName(_packageName, _packageVersion);
|
||||
string webURL = GetPatchManifestRequestURL(fileName);
|
||||
YooLogger.Log($"Beginning to request patch manifest : {webURL}");
|
||||
_downloader2 = new UnityWebDataRequester();
|
||||
_downloader2.SendRequest(webURL, _timeout);
|
||||
_steps = ESteps.CheckWebManifest;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.CheckWebManifest)
|
||||
{
|
||||
if (_downloader2.IsDone() == false)
|
||||
return;
|
||||
|
||||
if (_downloader2.HasError())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = _downloader2.GetError();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
string content = _downloader2.GetText();
|
||||
var manifest = PersistentHelper.SaveCacheManifestFile(_packageName, content);
|
||||
_impl.SetLocalPatchManifest(manifest);
|
||||
FoundNewManifest = true;
|
||||
_steps = ESteps.InitVerifyingCache;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Failed;
|
||||
Error = e.Message;
|
||||
}
|
||||
}
|
||||
_downloader2.Dispose();
|
||||
}
|
||||
|
||||
if (_steps == ESteps.InitVerifyingCache)
|
||||
{
|
||||
var verifyInfos = _impl.GetVerifyInfoList(false);
|
||||
_cacheVerifier.InitVerifier(verifyInfos);
|
||||
_verifyTime = UnityEngine.Time.realtimeSinceStartup;
|
||||
_steps = ESteps.UpdateVerifyingCache;
|
||||
}
|
||||
|
||||
if (_steps == ESteps.UpdateVerifyingCache)
|
||||
{
|
||||
Progress = _cacheVerifier.GetVerifierProgress();
|
||||
if (_cacheVerifier.UpdateVerifier())
|
||||
{
|
||||
_steps = ESteps.Done;
|
||||
Status = EOperationStatus.Succeed;
|
||||
float costTime = UnityEngine.Time.realtimeSinceStartup - _verifyTime;
|
||||
YooLogger.Log($"Verify result : Success {_cacheVerifier.VerifySuccessList.Count}, Fail {_cacheVerifier.VerifyFailList.Count}, Elapsed time {costTime} seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁清单请求地址
|
||||
/// </summary>
|
||||
private string GetPatchManifestRequestURL(string fileName)
|
||||
{
|
||||
// 轮流返回请求地址
|
||||
if (RequestCount % 2 == 0)
|
||||
return _impl.GetPatchDownloadFallbackURL(fileName);
|
||||
else
|
||||
return _impl.GetPatchDownloadMainURL(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ using UnityEngine;
|
||||
namespace YooAsset
|
||||
{
|
||||
/// <summary>
|
||||
/// 更新静态版本操作
|
||||
/// 请求远端包裹的最新版本
|
||||
/// </summary>
|
||||
public abstract class UpdateStaticVersionOperation : AsyncOperationBase
|
||||
public abstract class UpdatePackageVersionOperation : AsyncOperationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前最新的包裹版本
|
||||
@@ -16,9 +16,9 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑器下模拟运行的更新静态版本操作
|
||||
/// 编辑器下模拟模式的请求远端包裹的最新版本
|
||||
/// </summary>
|
||||
internal sealed class EditorPlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
|
||||
internal sealed class EditorPlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
@@ -30,9 +30,9 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离线模式的更新静态版本操作
|
||||
/// 离线模式的请求远端包裹的最新版本
|
||||
/// </summary>
|
||||
internal sealed class OfflinePlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
|
||||
internal sealed class OfflinePlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
|
||||
{
|
||||
internal override void Start()
|
||||
{
|
||||
@@ -44,9 +44,9 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 联机模式的更新静态版本操作
|
||||
/// 联机模式的请求远端包裹的最新版本
|
||||
/// </summary>
|
||||
internal sealed class HostPlayModeUpdateStaticVersionOperation : UpdateStaticVersionOperation
|
||||
internal sealed class HostPlayModeUpdatePackageVersionOperation : UpdatePackageVersionOperation
|
||||
{
|
||||
private enum ESteps
|
||||
{
|
||||
@@ -63,7 +63,7 @@ namespace YooAsset
|
||||
private ESteps _steps = ESteps.None;
|
||||
private UnityWebDataRequester _downloader;
|
||||
|
||||
internal HostPlayModeUpdateStaticVersionOperation(HostPlayModeImpl impl, string packageName, int timeout)
|
||||
internal HostPlayModeUpdatePackageVersionOperation(HostPlayModeImpl impl, string packageName, int timeout)
|
||||
{
|
||||
_impl = impl;
|
||||
_packageName = packageName;
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
@@ -27,31 +26,26 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public long FileSize;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile;
|
||||
|
||||
/// <summary>
|
||||
/// 加载方法
|
||||
/// </summary>
|
||||
public byte LoadMethod;
|
||||
|
||||
/// <summary>
|
||||
/// 资源包的分类标签
|
||||
/// </summary>
|
||||
public string[] Tags;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Flags
|
||||
/// 所属的包裹名称
|
||||
/// </summary>
|
||||
public int Flags;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否为原生文件
|
||||
/// </summary>
|
||||
public bool IsRawFile { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为加密文件
|
||||
/// </summary>
|
||||
public bool IsEncrypted { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// </summary>
|
||||
public string FileName { private set; get; }
|
||||
private string _packageName;
|
||||
|
||||
/// <summary>
|
||||
/// 缓存文件路径
|
||||
@@ -64,7 +58,7 @@ namespace YooAsset
|
||||
if (string.IsNullOrEmpty(_cachedFilePath) == false)
|
||||
return _cachedFilePath;
|
||||
|
||||
string cacheRoot = SandboxHelper.GetCacheFolderPath();
|
||||
string cacheRoot = PersistentHelper.GetCacheFolderPath(_packageName);
|
||||
_cachedFilePath = $"{cacheRoot}/{FileName}";
|
||||
return _cachedFilePath;
|
||||
}
|
||||
@@ -86,70 +80,54 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件名称
|
||||
/// </summary>
|
||||
private string _fileName;
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_fileName))
|
||||
throw new Exception("Should never get here !");
|
||||
return _fileName;
|
||||
}
|
||||
}
|
||||
|
||||
public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, string[] tags)
|
||||
/// <summary>
|
||||
/// 缓存查询Key
|
||||
/// </summary>
|
||||
private string _cacheKey;
|
||||
public string CacheKey
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_cacheKey))
|
||||
throw new Exception("Should never get here !");
|
||||
return _cacheKey;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PatchBundle(string bundleName, string fileHash, string fileCRC, long fileSize, bool isRawFile, byte loadMethod, string[] tags)
|
||||
{
|
||||
BundleName = bundleName;
|
||||
FileHash = fileHash;
|
||||
FileCRC = fileCRC;
|
||||
FileSize = fileSize;
|
||||
IsRawFile = isRawFile;
|
||||
LoadMethod = loadMethod;
|
||||
Tags = tags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置Flags
|
||||
/// 解析资源包
|
||||
/// </summary>
|
||||
public void SetFlagsValue(bool isRawFile, bool isEncrypted)
|
||||
public void ParseBundle(string packageName, int nameStype)
|
||||
{
|
||||
IsRawFile = isRawFile;
|
||||
IsEncrypted = isEncrypted;
|
||||
|
||||
BitMask32 mask = new BitMask32(0);
|
||||
if (isRawFile) mask.Open(0);
|
||||
if (isEncrypted) mask.Open(1);
|
||||
Flags = mask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析Flags
|
||||
/// </summary>
|
||||
public void ParseFlagsValue()
|
||||
{
|
||||
BitMask32 value = Flags;
|
||||
IsRawFile = value.Test(0);
|
||||
IsEncrypted = value.Test(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析文件名称
|
||||
/// </summary>
|
||||
public void ParseFileName(int nameStype)
|
||||
{
|
||||
if (nameStype == 1)
|
||||
{
|
||||
FileName = FileHash;
|
||||
}
|
||||
else if (nameStype == 2)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(BundleName);
|
||||
FileName = $"{FileHash}{tempFileExtension}";
|
||||
}
|
||||
else if (nameStype == 3)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(BundleName);
|
||||
string tempBundleName = BundleName.Replace('/', '_').Replace(tempFileExtension, "");
|
||||
FileName = $"{tempBundleName}_{FileHash}";
|
||||
}
|
||||
else if (nameStype == 4)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(BundleName);
|
||||
string tempBundleName = BundleName.Replace('/', '_').Replace(tempFileExtension, "");
|
||||
FileName = $"{tempBundleName}_{FileHash}{tempFileExtension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
_packageName = packageName;
|
||||
_cacheKey = $"{packageName}-{FileHash}";
|
||||
_fileName = PatchManifest.CreateBundleFileName(nameStype, BundleName, FileHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -247,6 +247,23 @@ namespace YooAsset
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源信息列表
|
||||
/// </summary>
|
||||
public AssetInfo[] GetAssetsInfoByTags(string[] tags)
|
||||
{
|
||||
List<AssetInfo> result = new List<AssetInfo>(100);
|
||||
foreach (var patchAsset in AssetList)
|
||||
{
|
||||
if (patchAsset.HasTag(tags))
|
||||
{
|
||||
AssetInfo assetInfo = new AssetInfo(patchAsset);
|
||||
result.Add(assetInfo);
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
@@ -263,6 +280,8 @@ namespace YooAsset
|
||||
public static PatchManifest Deserialize(string jsonData)
|
||||
{
|
||||
PatchManifest patchManifest = JsonUtility.FromJson<PatchManifest>(jsonData);
|
||||
if (patchManifest == null)
|
||||
throw new System.Exception($"{nameof(PatchManifest)} deserialize object is null !");
|
||||
|
||||
// 检测文件版本
|
||||
if (patchManifest.FileVersion != YooAssetSettings.PatchManifestFileVersion)
|
||||
@@ -271,8 +290,7 @@ namespace YooAsset
|
||||
// BundleList
|
||||
foreach (var patchBundle in patchManifest.BundleList)
|
||||
{
|
||||
patchBundle.ParseFlagsValue();
|
||||
patchBundle.ParseFileName(patchManifest.OutputNameStyle);
|
||||
patchBundle.ParseBundle(patchManifest.PackageName, patchManifest.OutputNameStyle);
|
||||
patchManifest.BundleDic.Add(patchBundle.BundleName, patchBundle);
|
||||
}
|
||||
|
||||
@@ -289,5 +307,37 @@ namespace YooAsset
|
||||
|
||||
return patchManifest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成Bundle文件的正式名称
|
||||
/// </summary>
|
||||
public static string CreateBundleFileName(int nameStype, string bundleName, string fileHash)
|
||||
{
|
||||
if (nameStype == 1)
|
||||
{
|
||||
return fileHash;
|
||||
}
|
||||
else if (nameStype == 2)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(bundleName);
|
||||
return $"{fileHash}{tempFileExtension}";
|
||||
}
|
||||
else if (nameStype == 3)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(bundleName);
|
||||
string tempBundleName = bundleName.Replace('/', '_').Replace(tempFileExtension, "");
|
||||
return $"{tempBundleName}_{fileHash}";
|
||||
}
|
||||
else if (nameStype == 4)
|
||||
{
|
||||
string tempFileExtension = System.IO.Path.GetExtension(bundleName);
|
||||
string tempBundleName = bundleName.Replace('/', '_').Replace(tempFileExtension, "");
|
||||
return $"{tempBundleName}_{fileHash}{tempFileExtension}";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace YooAsset
|
||||
}
|
||||
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
|
||||
{
|
||||
return PatchHelper.GetAssetsInfoByTags(_simulatePatchManifest, tags);
|
||||
return _simulatePatchManifest.GetAssetsInfoByTags(tags);
|
||||
}
|
||||
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
|
||||
{
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 异步更新资源版本号
|
||||
/// </summary>
|
||||
public UpdateStaticVersionOperation UpdateStaticVersionAsync(string packageName, int timeout)
|
||||
public UpdatePackageVersionOperation UpdatePackageVersionAsync(string packageName, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModeUpdateStaticVersionOperation(this, packageName, timeout);
|
||||
var operation = new HostPlayModeUpdatePackageVersionOperation(this, packageName, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
@@ -54,19 +54,19 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 异步更新补丁清单
|
||||
/// </summary>
|
||||
public UpdateManifestOperation UpdatePatchManifestAsync(string packageName, string packageVersion, int timeout)
|
||||
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModeUpdateManifestOperation(this, packageName, packageVersion, timeout);
|
||||
var operation = new HostPlayModeUpdatePackageManifestOperation(this, packageName, packageVersion, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步更新补丁清单(弱联网)
|
||||
/// 检查本地包裹内容的完整性
|
||||
/// </summary>
|
||||
public UpdateManifestOperation WeaklyUpdatePatchManifestAsync(string packageName, string packageVersion)
|
||||
public CheckPackageContentsOperation CheckPackageContentsAsync(string packageName)
|
||||
{
|
||||
var operation = new HostPlayModeWeaklyUpdateManifestOperation(this, packageName, packageVersion);
|
||||
var operation = new HostPlayModeCheckPackageContentsOperation(this, packageName);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
@@ -74,9 +74,9 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 异步更新资源包裹
|
||||
/// </summary>
|
||||
public UpdatePackageOperation UpdatePackageAsync(string packageName, string packageVersion, int timeout)
|
||||
public DownloadPackageOperation DownloadPackageAsync(string packageName, string packageVersion, int timeout)
|
||||
{
|
||||
var operation = new HostPlayModeUpdatePackageOperation(this, packageName, packageVersion, timeout);
|
||||
var operation = new HostPlayModeDownloadPackageOperation(this, packageName, packageVersion, timeout);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
@@ -86,6 +86,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public PatchDownloaderOperation CreatePatchDownloaderByAll(int fileLoadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
YooLogger.Log($"Create patch downloader : {LocalPatchManifest.PackageName} {LocalPatchManifest.PackageVersion}");
|
||||
List<BundleInfo> downloadList = GetDownloadListByAll();
|
||||
var operation = new PatchDownloaderOperation(downloadList, fileLoadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
@@ -114,6 +115,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public PatchDownloaderOperation CreatePatchDownloaderByTags(string[] tags, int fileLoadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
YooLogger.Log($"Create patch downloader : {LocalPatchManifest.PackageName} {LocalPatchManifest.PackageVersion}");
|
||||
List<BundleInfo> downloadList = GetDownloadListByTags(tags);
|
||||
var operation = new PatchDownloaderOperation(downloadList, fileLoadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
@@ -154,6 +156,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public PatchDownloaderOperation CreatePatchDownloaderByPaths(AssetInfo[] assetInfos, int fileLoadingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
YooLogger.Log($"Create patch downloader : {LocalPatchManifest.PackageName} {LocalPatchManifest.PackageVersion}");
|
||||
List<BundleInfo> downloadList = GetDownloadListByPaths(assetInfos);
|
||||
var operation = new PatchDownloaderOperation(downloadList, fileLoadingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
@@ -206,6 +209,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public PatchUnpackerOperation CreatePatchUnpackerByTags(string[] tags, int fileUpackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
YooLogger.Log($"Create patch unpacker : {LocalPatchManifest.PackageName} {LocalPatchManifest.PackageVersion}");
|
||||
List<BundleInfo> unpcakList = GetUnpackListByTags(tags);
|
||||
var operation = new PatchUnpackerOperation(unpcakList, fileUpackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
@@ -229,7 +233,7 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
return PatchHelper.ConvertToUnpackList(downloadList);
|
||||
return ConvertToUnpackList(downloadList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -237,6 +241,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public PatchUnpackerOperation CreatePatchUnpackerByAll(int fileUpackingMaxNumber, int failedTryAgain, int timeout)
|
||||
{
|
||||
YooLogger.Log($"Create patch unpacker : {LocalPatchManifest.PackageName} {LocalPatchManifest.PackageVersion}");
|
||||
List<BundleInfo> unpcakList = GetUnpackListByAll();
|
||||
var operation = new PatchUnpackerOperation(unpcakList, fileUpackingMaxNumber, failedTryAgain, timeout);
|
||||
return operation;
|
||||
@@ -256,7 +261,7 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
return PatchHelper.ConvertToUnpackList(downloadList);
|
||||
return ConvertToUnpackList(downloadList);
|
||||
}
|
||||
|
||||
// WEB相关
|
||||
@@ -280,7 +285,7 @@ namespace YooAsset
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public BundleInfo ConvertToDownloadInfo(PatchBundle patchBundle)
|
||||
private BundleInfo ConvertToDownloadInfo(PatchBundle patchBundle)
|
||||
{
|
||||
string remoteMainURL = GetPatchDownloadMainURL(patchBundle.FileName);
|
||||
string remoteFallbackURL = GetPatchDownloadFallbackURL(patchBundle.FileName);
|
||||
@@ -288,6 +293,25 @@ namespace YooAsset
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
// 解压相关
|
||||
public List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList)
|
||||
{
|
||||
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
|
||||
foreach (var patchBundle in unpackList)
|
||||
{
|
||||
var bundleInfo = ConvertToUnpackInfo(patchBundle);
|
||||
result.Add(bundleInfo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
|
||||
{
|
||||
// 注意:我们把流加载路径指定为远端下载地址
|
||||
string streamingPath = PathHelper.ConvertToWWWPath(patchBundle.StreamingFilePath);
|
||||
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
|
||||
return bundleInfo;
|
||||
}
|
||||
|
||||
internal List<VerifyInfo> GetVerifyInfoList(bool weaklyUpdateMode)
|
||||
{
|
||||
List<VerifyInfo> result = new List<VerifyInfo>(LocalPatchManifest.BundleList.Count);
|
||||
@@ -379,7 +403,7 @@ namespace YooAsset
|
||||
}
|
||||
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
|
||||
{
|
||||
return PatchHelper.GetAssetsInfoByTags(LocalPatchManifest, tags);
|
||||
return LocalPatchManifest.GetAssetsInfoByTags(tags);
|
||||
}
|
||||
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace YooAsset
|
||||
}
|
||||
AssetInfo[] IBundleServices.GetAssetInfos(string[] tags)
|
||||
{
|
||||
return PatchHelper.GetAssetsInfoByTags(_appPatchManifest, tags);
|
||||
return _appPatchManifest.GetAssetsInfoByTags(tags);
|
||||
}
|
||||
PatchAsset IBundleServices.TryGetPatchAsset(string assetPath)
|
||||
{
|
||||
|
||||
@@ -1,17 +1,42 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public struct DecryptionFileInfo
|
||||
public struct DecryptFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
public string FileHash;
|
||||
|
||||
/// <summary>
|
||||
/// 文件路径
|
||||
/// </summary>
|
||||
public string FilePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解密类服务接口
|
||||
/// </summary>
|
||||
public interface IDecryptionServices
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取加密文件的数据偏移量
|
||||
/// 文件偏移解密方法
|
||||
/// </summary>
|
||||
ulong GetFileOffset(DecryptionFileInfo fileInfo);
|
||||
ulong LoadFromFileOffset(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件内存解密方法
|
||||
/// </summary>
|
||||
byte[] LoadFromMemory(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件流解密方法
|
||||
/// </summary>
|
||||
System.IO.FileStream LoadFromStream(DecryptFileInfo fileInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 文件流解密的托管缓存大小
|
||||
/// </summary>
|
||||
uint GetManagedReadBufferSize();
|
||||
}
|
||||
}
|
||||
37
Assets/YooAsset/Runtime/Services/IEncryptionServices.cs
Normal file
37
Assets/YooAsset/Runtime/Services/IEncryptionServices.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
public struct EncryptResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 加密后的Bunlde文件加载方法
|
||||
/// </summary>
|
||||
public EBundleLoadMethod LoadMethod;
|
||||
|
||||
/// <summary>
|
||||
/// 加密后的文件数据
|
||||
/// </summary>
|
||||
public byte[] EncryptedData;
|
||||
}
|
||||
|
||||
public struct EncryptFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 资源包名称
|
||||
/// </summary>
|
||||
public string BundleName;
|
||||
|
||||
/// <summary>
|
||||
/// 文件路径
|
||||
/// </summary>
|
||||
public string FilePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加密服务类接口
|
||||
/// </summary>
|
||||
public interface IEncryptionServices
|
||||
{
|
||||
EncryptResult Encrypt(EncryptFileInfo fileInfo);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace YooAsset
|
||||
/// <summary>
|
||||
/// 补丁清单文件格式版本
|
||||
/// </summary>
|
||||
public const string PatchManifestFileVersion = "1.3.3";
|
||||
public const string PatchManifestFileVersion = "1.3.4";
|
||||
|
||||
/// <summary>
|
||||
/// 构建输出文件夹名称
|
||||
|
||||
@@ -40,6 +40,14 @@ namespace YooAsset
|
||||
return $"{YooAssetSettings.ReportFileName}_{packageName}_{packageVersion}.json";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁清单文件不带版本号的名称
|
||||
/// </summary>
|
||||
public static string GetPatchManifestFileNameWithoutVersion(string packageName)
|
||||
{
|
||||
return $"{Setting.PatchManifestFileName}_{packageName}.bytes";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取补丁清单文件完整名称
|
||||
/// </summary>
|
||||
|
||||
@@ -76,9 +76,9 @@ namespace YooAsset
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 沙盒帮助类
|
||||
/// 持久化目录帮助类
|
||||
/// </summary>
|
||||
internal static class SandboxHelper
|
||||
internal static class PersistentHelper
|
||||
{
|
||||
private const string CacheFolderName = "CacheFiles";
|
||||
|
||||
@@ -97,61 +97,79 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public static void DeleteCacheFolder()
|
||||
{
|
||||
string directoryPath = GetCacheFolderPath();
|
||||
if (Directory.Exists(directoryPath))
|
||||
Directory.Delete(directoryPath, true);
|
||||
string root = PathHelper.MakePersistentLoadPath(CacheFolderName);
|
||||
if (Directory.Exists(root))
|
||||
Directory.Delete(root, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存文件夹路径
|
||||
/// </summary>
|
||||
public static string GetCacheFolderPath()
|
||||
public static string GetCacheFolderPath(string packageName)
|
||||
{
|
||||
return PathHelper.MakePersistentLoadPath(CacheFolderName);
|
||||
string root = PathHelper.MakePersistentLoadPath(CacheFolderName);
|
||||
return $"{root}/{packageName}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 补丁包帮助类
|
||||
/// </summary>
|
||||
internal static class PatchHelper
|
||||
{
|
||||
#region 沙盒内清单相关
|
||||
/// <summary>
|
||||
/// 获取资源信息列表
|
||||
/// 获取沙盒内清单文件的路径
|
||||
/// </summary>
|
||||
public static AssetInfo[] GetAssetsInfoByTags(PatchManifest patchManifest, string[] tags)
|
||||
public static string GetCacheManifestFilePath(string packageName)
|
||||
{
|
||||
List<AssetInfo> result = new List<AssetInfo>(100);
|
||||
foreach (var patchAsset in patchManifest.AssetList)
|
||||
{
|
||||
if(patchAsset.HasTag(tags))
|
||||
{
|
||||
AssetInfo assetInfo = new AssetInfo(patchAsset);
|
||||
result.Add(assetInfo);
|
||||
}
|
||||
}
|
||||
return result.ToArray();
|
||||
string fileName = YooAssetSettingsData.GetPatchManifestFileNameWithoutVersion(packageName);
|
||||
return PathHelper.MakePersistentLoadPath(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源解压相关
|
||||
/// 加载沙盒内清单文件
|
||||
/// </summary>
|
||||
public static List<BundleInfo> ConvertToUnpackList(List<PatchBundle> unpackList)
|
||||
public static PatchManifest LoadCacheManifestFile(string packageName)
|
||||
{
|
||||
List<BundleInfo> result = new List<BundleInfo>(unpackList.Count);
|
||||
foreach (var patchBundle in unpackList)
|
||||
YooLogger.Log($"Load sandbox patch manifest file : {packageName}");
|
||||
string filePath = GetCacheManifestFilePath(packageName);
|
||||
string jsonData = File.ReadAllText(filePath);
|
||||
return PatchManifest.Deserialize(jsonData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 存储沙盒内清单文件
|
||||
/// </summary>
|
||||
public static PatchManifest SaveCacheManifestFile(string packageName, string fileContent)
|
||||
{
|
||||
YooLogger.Log($"Save sandbox patch manifest file : {packageName}");
|
||||
var manifest = PatchManifest.Deserialize(fileContent);
|
||||
string savePath = GetCacheManifestFilePath(packageName);
|
||||
FileUtility.CreateFile(savePath, fileContent);
|
||||
return manifest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测沙盒内清单文件是否存在
|
||||
/// </summary>
|
||||
public static bool CheckCacheManifestFileExists(string packageName)
|
||||
{
|
||||
string filePath = GetCacheManifestFilePath(packageName);
|
||||
return File.Exists(filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除沙盒内清单文件
|
||||
/// </summary>
|
||||
public static bool DeleteCacheManifestFile(string packageName)
|
||||
{
|
||||
string filePath = GetCacheManifestFilePath(packageName);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var bundleInfo = ConvertToUnpackInfo(patchBundle);
|
||||
result.Add(bundleInfo);
|
||||
YooLogger.Warning($"Invalid cache manifest file have been removed : {filePath}");
|
||||
File.Delete(filePath);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static BundleInfo ConvertToUnpackInfo(PatchBundle patchBundle)
|
||||
{
|
||||
// 注意:我们把流加载路径指定为远端下载地址
|
||||
string streamingPath = PathHelper.ConvertToWWWPath(patchBundle.StreamingFilePath);
|
||||
BundleInfo bundleInfo = new BundleInfo(patchBundle, BundleInfo.ELoadMode.LoadFromStreaming, streamingPath, streamingPath);
|
||||
return bundleInfo;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -148,6 +148,27 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件(如果已经存在则删除旧文件)
|
||||
/// </summary>
|
||||
public static void CreateFile(string filePath, byte[] data)
|
||||
{
|
||||
// 删除旧文件
|
||||
if (File.Exists(filePath))
|
||||
File.Delete(filePath);
|
||||
|
||||
// 创建文件夹路径
|
||||
CreateFileDirectory(filePath);
|
||||
|
||||
// 创建新文件
|
||||
using (FileStream fs = File.Create(filePath))
|
||||
{
|
||||
fs.Write(data, 0, data.Length);
|
||||
fs.Flush();
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建文件的文件夹路径
|
||||
/// </summary>
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace YooAsset
|
||||
public static partial class YooAssets
|
||||
{
|
||||
private static bool _isInitialize = false;
|
||||
private static GameObject _driver = null;
|
||||
private static readonly List<AssetsPackage> _packages = new List<AssetsPackage>();
|
||||
|
||||
/// <summary>
|
||||
@@ -23,13 +24,14 @@ namespace YooAsset
|
||||
{
|
||||
// 创建驱动器
|
||||
_isInitialize = true;
|
||||
UnityEngine.GameObject driverGo = new UnityEngine.GameObject($"[{nameof(YooAssets)}]");
|
||||
driverGo.AddComponent<YooAssetsDriver>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(driverGo);
|
||||
_driver = new UnityEngine.GameObject($"[{nameof(YooAssets)}]");
|
||||
_driver.AddComponent<YooAssetsDriver>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(_driver);
|
||||
YooLogger.Log($"{nameof(YooAssets)} initialize !");
|
||||
|
||||
#if DEBUG
|
||||
// 添加远程调试脚本
|
||||
driverGo.AddComponent<RemoteDebuggerInRuntime>();
|
||||
_driver.AddComponent<RemoteDebuggerInRuntime>();
|
||||
#endif
|
||||
|
||||
// 初始化异步系统
|
||||
@@ -37,27 +39,10 @@ namespace YooAsset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新资源系统
|
||||
/// </summary>
|
||||
internal static void Update()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
OperationSystem.Update();
|
||||
DownloadSystem.Update();
|
||||
|
||||
foreach (var package in _packages)
|
||||
{
|
||||
package.UpdatePackage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁资源系统
|
||||
/// </summary>
|
||||
internal static void Destroy()
|
||||
public static void Destroy()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
@@ -72,7 +57,26 @@ namespace YooAsset
|
||||
_packages.Clear();
|
||||
|
||||
_isInitialize = false;
|
||||
YooLogger.Log("YooAssets destroy all !");
|
||||
if (_driver != null)
|
||||
GameObject.Destroy(_driver);
|
||||
YooLogger.Log($"{nameof(YooAssets)} destroy all !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新资源系统
|
||||
/// </summary>
|
||||
internal static void Update()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
OperationSystem.Update();
|
||||
DownloadSystem.Update();
|
||||
|
||||
for (int i = 0; i < _packages.Count; i++)
|
||||
{
|
||||
_packages[i].UpdatePackage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,16 +197,6 @@ namespace YooAsset
|
||||
#endregion
|
||||
|
||||
#region 沙盒相关
|
||||
/// <summary>
|
||||
/// 清理未使用的缓存文件
|
||||
/// </summary>
|
||||
public static ClearUnusedCacheFilesOperation ClearUnusedCacheFiles()
|
||||
{
|
||||
ClearUnusedCacheFilesOperation operation = new ClearUnusedCacheFilesOperation(_packages);
|
||||
OperationSystem.StartOperation(operation);
|
||||
return operation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取内置文件夹名称
|
||||
/// </summary>
|
||||
@@ -224,7 +218,7 @@ namespace YooAsset
|
||||
/// </summary>
|
||||
public static void ClearSandbox()
|
||||
{
|
||||
SandboxHelper.DeleteSandbox();
|
||||
PersistentHelper.DeleteSandbox();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
using UnityEngine;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace YooAsset
|
||||
{
|
||||
internal class YooAssetsDriver : MonoBehaviour
|
||||
{
|
||||
private static int LastestUpdateFrame = 0;
|
||||
|
||||
void Update()
|
||||
{
|
||||
DebugCheckDuplicateDriver();
|
||||
YooAssets.Update();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
[Conditional("DEBUG")]
|
||||
private void DebugCheckDuplicateDriver()
|
||||
{
|
||||
YooAssets.Destroy();
|
||||
}
|
||||
if (LastestUpdateFrame > 0)
|
||||
{
|
||||
if (LastestUpdateFrame == Time.frameCount)
|
||||
YooLogger.Warning($"There are two {nameof(YooAssetsDriver)} in the scene. Please ensure there is always exactly one driver in the scene.");
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
YooAssets.Destroy();
|
||||
LastestUpdateFrame = Time.frameCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,25 +82,43 @@ namespace YooAsset
|
||||
|
||||
#region 原生文件
|
||||
/// <summary>
|
||||
/// 异步获取原生文件
|
||||
/// 同步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
/// <param name="copyPath">拷贝路径</param>
|
||||
public static RawFileOperation GetRawFileAsync(string location, string copyPath = null)
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public static RawFileOperationHandle LoadRawFileSync(AssetInfo assetInfo)
|
||||
{
|
||||
DebugCheckDefaultPackageValid();
|
||||
return _defaultPackage.GetRawFileAsync(location, copyPath);
|
||||
return _defaultPackage.LoadRawFileSync(assetInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取原生文件
|
||||
/// 同步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
/// <param name="copyPath">拷贝路径</param>
|
||||
public static RawFileOperation GetRawFileAsync(AssetInfo assetInfo, string copyPath = null)
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public static RawFileOperationHandle LoadRawFileSync(string location)
|
||||
{
|
||||
DebugCheckDefaultPackageValid();
|
||||
return _defaultPackage.GetRawFileAsync(assetInfo, copyPath);
|
||||
return _defaultPackage.LoadRawFileSync(location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息</param>
|
||||
public static RawFileOperationHandle LoadRawFileAsync(AssetInfo assetInfo)
|
||||
{
|
||||
DebugCheckDefaultPackageValid();
|
||||
return _defaultPackage.LoadRawFileAsync(assetInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载原生文件
|
||||
/// </summary>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public static RawFileOperationHandle LoadRawFileAsync(string location)
|
||||
{
|
||||
DebugCheckDefaultPackageValid();
|
||||
return _defaultPackage.LoadRawFileAsync(location);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -367,14 +385,14 @@ namespace YooAsset
|
||||
|
||||
#region 包裹更新
|
||||
/// <summary>
|
||||
/// 创建资源包裹下载器,用于下载更新指定资源版本所有的资源包文件
|
||||
/// 资源包裹更新,用于下载更新指定资源版本所有的资源包文件
|
||||
/// </summary>
|
||||
/// <param name="packageVersion">指定更新的包裹版本</param>
|
||||
/// <param name="timeout">超时时间</param>
|
||||
public static UpdatePackageOperation UpdatePackageAsync(string packageVersion, int timeout = 60)
|
||||
public static DownloadPackageOperation DownloadPackageAsync(string packageVersion, int timeout = 60)
|
||||
{
|
||||
DebugCheckDefaultPackageValid();
|
||||
return _defaultPackage.UpdatePackageAsync(packageVersion, timeout);
|
||||
return _defaultPackage.DownloadPackageAsync(packageVersion, timeout);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,692 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67fa0069e75d5734fbeb60b68392703b
|
||||
ModelImporter:
|
||||
serializedVersion: 20200
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
1: 100000
|
||||
second: Chest
|
||||
- first:
|
||||
1: 100002
|
||||
second: COB_CTRL
|
||||
- first:
|
||||
1: 100004
|
||||
second: Foot_Left
|
||||
- first:
|
||||
1: 100006
|
||||
second: Foot_Right
|
||||
- first:
|
||||
1: 100008
|
||||
second: //RootNode
|
||||
- first:
|
||||
1: 100010
|
||||
second: Footman_Mesh
|
||||
- first:
|
||||
1: 100012
|
||||
second: Hand_Left
|
||||
- first:
|
||||
1: 100014
|
||||
second: Hand_Right
|
||||
- first:
|
||||
1: 100016
|
||||
second: Head
|
||||
- first:
|
||||
1: 100018
|
||||
second: Hips
|
||||
- first:
|
||||
1: 100020
|
||||
second: Index_Intermediate_Left
|
||||
- first:
|
||||
1: 100022
|
||||
second: Index_Intermediate_Right
|
||||
- first:
|
||||
1: 100024
|
||||
second: Index_Proximal_Left
|
||||
- first:
|
||||
1: 100026
|
||||
second: Index_Proximal_Right
|
||||
- first:
|
||||
1: 100028
|
||||
second: J_Tip
|
||||
- first:
|
||||
1: 100030
|
||||
second: Jaw
|
||||
- first:
|
||||
1: 100032
|
||||
second: LowerArm_Left
|
||||
- first:
|
||||
1: 100034
|
||||
second: LowerArm_Right
|
||||
- first:
|
||||
1: 100036
|
||||
second: LowerLeg_Left
|
||||
- first:
|
||||
1: 100038
|
||||
second: LowerLeg_Right
|
||||
- first:
|
||||
1: 100040
|
||||
second: Neck
|
||||
- first:
|
||||
1: 100042
|
||||
second: RestOfFingers_Intermediate_Left
|
||||
- first:
|
||||
1: 100044
|
||||
second: RestOfFingers_Intermediate_Right
|
||||
- first:
|
||||
1: 100046
|
||||
second: RestOfFingers_Proximal_Left
|
||||
- first:
|
||||
1: 100048
|
||||
second: RestOfFingers_Proximal_Right
|
||||
- first:
|
||||
1: 100050
|
||||
second: Shield
|
||||
- first:
|
||||
1: 100052
|
||||
second: Shoulder_Left
|
||||
- first:
|
||||
1: 100054
|
||||
second: Shoulder_Right
|
||||
- first:
|
||||
1: 100056
|
||||
second: Spine
|
||||
- first:
|
||||
1: 100058
|
||||
second: Sword
|
||||
- first:
|
||||
1: 100060
|
||||
second: Thumb_Intermediate_Left
|
||||
- first:
|
||||
1: 100062
|
||||
second: Thumb_Intermediate_Right
|
||||
- first:
|
||||
1: 100064
|
||||
second: Thumb_Proximal_Left
|
||||
- first:
|
||||
1: 100066
|
||||
second: Thumb_Proximal_Right
|
||||
- first:
|
||||
1: 100068
|
||||
second: Toe_Left
|
||||
- first:
|
||||
1: 100070
|
||||
second: Toe_Right
|
||||
- first:
|
||||
1: 100072
|
||||
second: Toetip_Left
|
||||
- first:
|
||||
1: 100074
|
||||
second: Toetip_Right
|
||||
- first:
|
||||
1: 100076
|
||||
second: UpperArm_Left
|
||||
- first:
|
||||
1: 100078
|
||||
second: UpperArm_Right
|
||||
- first:
|
||||
1: 100080
|
||||
second: UpperLeg_Left
|
||||
- first:
|
||||
1: 100082
|
||||
second: UpperLeg_Right
|
||||
- first:
|
||||
4: 400000
|
||||
second: Chest
|
||||
- first:
|
||||
4: 400002
|
||||
second: COB_CTRL
|
||||
- first:
|
||||
4: 400004
|
||||
second: Foot_Left
|
||||
- first:
|
||||
4: 400006
|
||||
second: Foot_Right
|
||||
- first:
|
||||
4: 400008
|
||||
second: //RootNode
|
||||
- first:
|
||||
4: 400010
|
||||
second: Footman_Mesh
|
||||
- first:
|
||||
4: 400012
|
||||
second: Hand_Left
|
||||
- first:
|
||||
4: 400014
|
||||
second: Hand_Right
|
||||
- first:
|
||||
4: 400016
|
||||
second: Head
|
||||
- first:
|
||||
4: 400018
|
||||
second: Hips
|
||||
- first:
|
||||
4: 400020
|
||||
second: Index_Intermediate_Left
|
||||
- first:
|
||||
4: 400022
|
||||
second: Index_Intermediate_Right
|
||||
- first:
|
||||
4: 400024
|
||||
second: Index_Proximal_Left
|
||||
- first:
|
||||
4: 400026
|
||||
second: Index_Proximal_Right
|
||||
- first:
|
||||
4: 400028
|
||||
second: J_Tip
|
||||
- first:
|
||||
4: 400030
|
||||
second: Jaw
|
||||
- first:
|
||||
4: 400032
|
||||
second: LowerArm_Left
|
||||
- first:
|
||||
4: 400034
|
||||
second: LowerArm_Right
|
||||
- first:
|
||||
4: 400036
|
||||
second: LowerLeg_Left
|
||||
- first:
|
||||
4: 400038
|
||||
second: LowerLeg_Right
|
||||
- first:
|
||||
4: 400040
|
||||
second: Neck
|
||||
- first:
|
||||
4: 400042
|
||||
second: RestOfFingers_Intermediate_Left
|
||||
- first:
|
||||
4: 400044
|
||||
second: RestOfFingers_Intermediate_Right
|
||||
- first:
|
||||
4: 400046
|
||||
second: RestOfFingers_Proximal_Left
|
||||
- first:
|
||||
4: 400048
|
||||
second: RestOfFingers_Proximal_Right
|
||||
- first:
|
||||
4: 400050
|
||||
second: Shield
|
||||
- first:
|
||||
4: 400052
|
||||
second: Shoulder_Left
|
||||
- first:
|
||||
4: 400054
|
||||
second: Shoulder_Right
|
||||
- first:
|
||||
4: 400056
|
||||
second: Spine
|
||||
- first:
|
||||
4: 400058
|
||||
second: Sword
|
||||
- first:
|
||||
4: 400060
|
||||
second: Thumb_Intermediate_Left
|
||||
- first:
|
||||
4: 400062
|
||||
second: Thumb_Intermediate_Right
|
||||
- first:
|
||||
4: 400064
|
||||
second: Thumb_Proximal_Left
|
||||
- first:
|
||||
4: 400066
|
||||
second: Thumb_Proximal_Right
|
||||
- first:
|
||||
4: 400068
|
||||
second: Toe_Left
|
||||
- first:
|
||||
4: 400070
|
||||
second: Toe_Right
|
||||
- first:
|
||||
4: 400072
|
||||
second: Toetip_Left
|
||||
- first:
|
||||
4: 400074
|
||||
second: Toetip_Right
|
||||
- first:
|
||||
4: 400076
|
||||
second: UpperArm_Left
|
||||
- first:
|
||||
4: 400078
|
||||
second: UpperArm_Right
|
||||
- first:
|
||||
4: 400080
|
||||
second: UpperLeg_Left
|
||||
- first:
|
||||
4: 400082
|
||||
second: UpperLeg_Right
|
||||
- first:
|
||||
43: 4300000
|
||||
second: Footman_Mesh
|
||||
- first:
|
||||
74: 7400000
|
||||
second: attack
|
||||
- first:
|
||||
95: 9500000
|
||||
second: //RootNode
|
||||
- first:
|
||||
111: 11100000
|
||||
second: //RootNode
|
||||
- first:
|
||||
137: 13700000
|
||||
second: Footman_Mesh
|
||||
externalObjects: {}
|
||||
materials:
|
||||
materialImportMode: 1
|
||||
materialName: 0
|
||||
materialSearch: 1
|
||||
materialLocation: 0
|
||||
animations:
|
||||
legacyGenerateAnimations: 4
|
||||
bakeSimulation: 0
|
||||
resampleCurves: 1
|
||||
optimizeGameObjects: 0
|
||||
motionNodeName:
|
||||
rigImportErrors:
|
||||
rigImportWarnings:
|
||||
animationImportErrors:
|
||||
animationImportWarnings:
|
||||
animationRetargetingWarnings:
|
||||
animationDoRetargetingWarnings: 0
|
||||
importAnimatedCustomProperties: 0
|
||||
importConstraints: 0
|
||||
animationCompression: 3
|
||||
animationRotationError: 0.5
|
||||
animationPositionError: 0.5
|
||||
animationScaleError: 0.5
|
||||
animationWrapMode: 0
|
||||
extraExposedTransformPaths: []
|
||||
extraUserProperties: []
|
||||
clipAnimations:
|
||||
- serializedVersion: 16
|
||||
name: attack
|
||||
takeName: Take 001
|
||||
internalID: 0
|
||||
firstFrame: 1
|
||||
lastFrame: 28
|
||||
wrapMode: 0
|
||||
orientationOffsetY: 0
|
||||
level: 0
|
||||
cycleOffset: 0
|
||||
loop: 0
|
||||
hasAdditiveReferencePose: 0
|
||||
loopTime: 1
|
||||
loopBlend: 0
|
||||
loopBlendOrientation: 1
|
||||
loopBlendPositionY: 1
|
||||
loopBlendPositionXZ: 1
|
||||
keepOriginalOrientation: 1
|
||||
keepOriginalPositionY: 1
|
||||
keepOriginalPositionXZ: 1
|
||||
heightFromFeet: 0
|
||||
mirror: 0
|
||||
bodyMask: 01000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000
|
||||
curves: []
|
||||
events: []
|
||||
transformMask:
|
||||
- path:
|
||||
weight: 1
|
||||
- path: COB_CTRL
|
||||
weight: 0
|
||||
- path: Footman_Mesh
|
||||
weight: 0
|
||||
- path: Hips
|
||||
weight: 1
|
||||
- path: Hips/Shield
|
||||
weight: 1
|
||||
- path: Hips/Spine
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Neck
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Neck/Head
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Neck/Head/Jaw
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Neck/Head/Jaw/J_Tip
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/Index_Proximal_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/Index_Proximal_Left/Index_Intermediate_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/RestOfFingers_Proximal_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/RestOfFingers_Proximal_Left/RestOfFingers_Intermediate_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/Thumb_Proximal_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Left/UpperArm_Left/LowerArm_Left/Hand_Left/Thumb_Proximal_Left/Thumb_Intermediate_Left
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/Index_Proximal_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/Index_Proximal_Right/Index_Intermediate_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/RestOfFingers_Proximal_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/RestOfFingers_Proximal_Right/RestOfFingers_Intermediate_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/Thumb_Proximal_Right
|
||||
weight: 1
|
||||
- path: Hips/Spine/Chest/Shoulder_Right/UpperArm_Right/LowerArm_Right/Hand_Right/Thumb_Proximal_Right/Thumb_Intermediate_Right
|
||||
weight: 1
|
||||
- path: Hips/Sword
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Left
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Left/LowerLeg_Left
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Left/LowerLeg_Left/Foot_Left
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Left/LowerLeg_Left/Foot_Left/Toe_Left
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Left/LowerLeg_Left/Foot_Left/Toe_Left/Toetip_Left
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Right
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Right/LowerLeg_Right
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Right/LowerLeg_Right/Foot_Right
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Right/LowerLeg_Right/Foot_Right/Toe_Right
|
||||
weight: 1
|
||||
- path: Hips/UpperLeg_Right/LowerLeg_Right/Foot_Right/Toe_Right/Toetip_Right
|
||||
weight: 1
|
||||
maskType: 0
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
isReadable: 1
|
||||
meshes:
|
||||
lODScreenPercentages: []
|
||||
globalScale: 1
|
||||
meshCompression: 0
|
||||
addColliders: 0
|
||||
useSRGBMaterialColor: 1
|
||||
sortHierarchyByName: 1
|
||||
importVisibility: 0
|
||||
importBlendShapes: 1
|
||||
importCameras: 0
|
||||
importLights: 0
|
||||
fileIdsGeneration: 1
|
||||
swapUVChannels: 0
|
||||
generateSecondaryUV: 0
|
||||
useFileUnits: 1
|
||||
keepQuads: 0
|
||||
weldVertices: 1
|
||||
bakeAxisConversion: 0
|
||||
preserveHierarchy: 0
|
||||
skinWeightsMode: 0
|
||||
maxBonesPerVertex: 4
|
||||
minBoneWeight: 0.001
|
||||
meshOptimizationFlags: -1
|
||||
indexFormat: 1
|
||||
secondaryUVAngleDistortion: 8
|
||||
secondaryUVAreaDistortion: 15.000001
|
||||
secondaryUVHardAngle: 88
|
||||
secondaryUVMarginMethod: 1
|
||||
secondaryUVMinLightmapResolution: 40
|
||||
secondaryUVMinObjectScale: 1
|
||||
secondaryUVPackMargin: 4
|
||||
useFileScale: 0
|
||||
tangentSpace:
|
||||
normalSmoothAngle: 60
|
||||
normalImportMode: 0
|
||||
tangentImportMode: 4
|
||||
normalCalculationMode: 0
|
||||
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 1
|
||||
blendShapeNormalImportMode: 1
|
||||
normalSmoothingSource: 0
|
||||
referencedClips: []
|
||||
importAnimation: 1
|
||||
humanDescription:
|
||||
serializedVersion: 3
|
||||
human: []
|
||||
skeleton:
|
||||
- name: footman@attack01(Clone)
|
||||
parentName:
|
||||
position: {x: 0, y: 0, z: 0}
|
||||
rotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
scale: {x: 1, y: 1, z: 1}
|
||||
- name: Footman_Mesh
|
||||
parentName: footman@attack01(Clone)
|
||||
position: {x: -0, y: 0, z: 0}
|
||||
rotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
scale: {x: 0.01, y: 0.01, z: 0.01}
|
||||
- name: COB_CTRL
|
||||
parentName: footman@attack01(Clone)
|
||||
position: {x: 0.0042852233, y: 0.6601113, z: -0.1711083}
|
||||
rotation: {x: 0.10958317, y: -0.19028346, z: -0.021378642, w: 0.9753598}
|
||||
scale: {x: 0.01, y: 0.01, z: 0.01}
|
||||
- name: Hips
|
||||
parentName: footman@attack01(Clone)
|
||||
position: {x: 0.0042852233, y: 0.7778554, z: 0.024665922}
|
||||
rotation: {x: 0.119579025, y: 0.11957903, z: -0.69692236, w: 0.6969225}
|
||||
scale: {x: 0.010000001, y: 0.009999999, z: 0.010000001}
|
||||
- name: Spine
|
||||
parentName: Hips
|
||||
position: {x: -22.08183, y: 2.7610132e-30, z: 2.789185e-15}
|
||||
rotation: {x: 0.000000007450581, y: -0.070730194, z: -0.000000078231096, w: 0.99749553}
|
||||
scale: {x: 1.0000006, y: 1.0000004, z: 0.99999994}
|
||||
- name: Chest
|
||||
parentName: Spine
|
||||
position: {x: -24.493395, y: 4.37078e-15, z: -6.5791713e-15}
|
||||
rotation: {x: 0.000000019903341, y: -0.1926707, z: -0.00000003972174, w: 0.98126346}
|
||||
scale: {x: 1.0000001, y: 1.0000002, z: 0.99999994}
|
||||
- name: Neck
|
||||
parentName: Chest
|
||||
position: {x: -31.697706, y: 4.2682918e-15, z: 1.5827795e-14}
|
||||
rotation: {x: -0.000000014372164, y: 0.14626887, z: -0.000000017028755, w: 0.9892449}
|
||||
scale: {x: 1.0000008, y: 1.0000006, z: 1.0000001}
|
||||
- name: Head
|
||||
parentName: Neck
|
||||
position: {x: -20.858675, y: 1.02066555e-14, z: 1.3950282e-15}
|
||||
rotation: {x: -0.38232452, y: -0.000000014134563, z: 0.92402816, w: -0.00000005207485}
|
||||
scale: {x: 1.0000002, y: 1, z: 0.99999976}
|
||||
- name: Jaw
|
||||
parentName: Head
|
||||
position: {x: -19.492151, y: -4.0412776e-15, z: -4.4981513}
|
||||
rotation: {x: -0.000000005806956, y: 0.0971892, z: 0.000000040794845, w: 0.99526596}
|
||||
scale: {x: 1.000001, y: 1.0000006, z: 1.0000001}
|
||||
- name: J_Tip
|
||||
parentName: Jaw
|
||||
position: {x: -9.274182, y: -1.2503675e-14, z: 8.099877}
|
||||
rotation: {x: 0.29965067, y: -0.2996506, z: -0.64047605, w: 0.640476}
|
||||
scale: {x: 0.99999994, y: 0.9999995, z: 1.0000008}
|
||||
- name: Shoulder_Left
|
||||
parentName: Chest
|
||||
position: {x: -18.98868, y: -31.335035, z: -12.155753}
|
||||
rotation: {x: -0.005294424, y: 0.090987876, z: 0.79941905, w: 0.59382015}
|
||||
scale: {x: 1, y: 1.0000002, z: 0.99999994}
|
||||
- name: UpperArm_Left
|
||||
parentName: Shoulder_Left
|
||||
position: {x: -14.901689, y: 2.842171e-14, z: 8.881784e-16}
|
||||
rotation: {x: 0.026086485, y: -0.107761614, z: -0.1623719, w: 0.9804807}
|
||||
scale: {x: 0.99999994, y: 0.99999964, z: 1.0000005}
|
||||
- name: LowerArm_Left
|
||||
parentName: UpperArm_Left
|
||||
position: {x: -32.191196, y: 4.842915e-15, z: -2.9871985e-15}
|
||||
rotation: {x: 0.00035523064, y: 0.064626634, z: 0.0047827335, w: 0.99789804}
|
||||
scale: {x: 0.9999998, y: 0.99999976, z: 0.9999998}
|
||||
- name: Hand_Left
|
||||
parentName: LowerArm_Left
|
||||
position: {x: -29.678864, y: -2.7758043e-29, z: 4.869975e-15}
|
||||
rotation: {x: -0.0033530025, y: -0.08887861, z: -0.072212294, w: 0.9934157}
|
||||
scale: {x: 1.0000004, y: 0.9999993, z: 0.9999999}
|
||||
- name: RestOfFingers_Proximal_Left
|
||||
parentName: Hand_Left
|
||||
position: {x: -18.280243, y: -1.6586086e-14, z: -2.029683e-15}
|
||||
rotation: {x: 0.0070363455, y: 0.038031247, z: 0.0719468, w: 0.9966583}
|
||||
scale: {x: 0.99999964, y: 1.0000008, z: 1.0000001}
|
||||
- name: RestOfFingers_Intermediate_Left
|
||||
parentName: RestOfFingers_Proximal_Left
|
||||
position: {x: -8.780147, y: 7.67957e-15, z: 3.7027159e-16}
|
||||
rotation: {x: 0.000000007916243, y: 0.02967007, z: 0.00000003856258, w: 0.99955976}
|
||||
scale: {x: 0.9999997, y: 1.0000001, z: 0.9999998}
|
||||
- name: Index_Proximal_Left
|
||||
parentName: Hand_Left
|
||||
position: {x: -16.901342, y: 1.1929646e-13, z: 10.104264}
|
||||
rotation: {x: 0.0067923637, y: 0.041410152, z: 0.07197031, w: 0.9965237}
|
||||
scale: {x: 0.9999993, y: 1.0000011, z: 1.0000001}
|
||||
- name: Index_Intermediate_Left
|
||||
parentName: Index_Proximal_Left
|
||||
position: {x: -9.911482, y: 1.4998595e-14, z: 3.154118e-15}
|
||||
rotation: {x: 0.00000002142042, y: 0.026280932, z: -0.000000027008355, w: 0.9996546}
|
||||
scale: {x: 1, y: 1.0000001, z: 1.0000001}
|
||||
- name: Thumb_Proximal_Left
|
||||
parentName: Hand_Left
|
||||
position: {x: -7.0572023, y: -4.708794, z: 9.280683}
|
||||
rotation: {x: -0.06620509, y: 0.3625553, z: 0.15769373, w: 0.91613495}
|
||||
scale: {x: 0.99999994, y: 1.0000007, z: 0.9999999}
|
||||
- name: Thumb_Intermediate_Left
|
||||
parentName: Thumb_Proximal_Left
|
||||
position: {x: -10.653726, y: 3.648137e-16, z: 8.5441255e-15}
|
||||
rotation: {x: 0.030814871, y: -0.21547182, z: -0.13817634, w: 0.9661934}
|
||||
scale: {x: 0.99999976, y: 1.0000004, z: 1.0000002}
|
||||
- name: Shoulder_Right
|
||||
parentName: Chest
|
||||
position: {x: -18.98899, y: 31.335, z: -12.155691}
|
||||
rotation: {x: 0.7994109, y: 0.59383136, z: 0.0052921963, w: -0.09098734}
|
||||
scale: {x: 1.0000002, y: 0.9999999, z: 1.0000001}
|
||||
- name: UpperArm_Right
|
||||
parentName: Shoulder_Right
|
||||
position: {x: 14.901961, y: 0.00046619424, z: 0.000079565914}
|
||||
rotation: {x: 0.107756816, y: 0.026086226, z: -0.9804833, w: -0.16235957}
|
||||
scale: {x: 1.0000002, y: 1, z: 1.0000007}
|
||||
- name: LowerArm_Right
|
||||
parentName: UpperArm_Right
|
||||
position: {x: -32.191166, y: 4.4336893e-14, z: 3.536796e-15}
|
||||
rotation: {x: -0.00035532357, y: -0.06462459, z: 0.0047840555, w: 0.99789816}
|
||||
scale: {x: 1.0000012, y: 1, z: 1.000001}
|
||||
- name: Hand_Right
|
||||
parentName: LowerArm_Right
|
||||
position: {x: -29.678719, y: 4.5461288e-14, z: -2.7325554e-15}
|
||||
rotation: {x: 0.0033532493, y: 0.08887915, z: -0.07221696, w: 0.99341536}
|
||||
scale: {x: 0.99999917, y: 1.0000001, z: 0.9999989}
|
||||
- name: RestOfFingers_Proximal_Right
|
||||
parentName: Hand_Right
|
||||
position: {x: -18.280209, y: -3.645552e-14, z: 1.8098782e-15}
|
||||
rotation: {x: -0.0070367483, y: -0.038032934, z: 0.07195137, w: 0.99665797}
|
||||
scale: {x: 0.99999994, y: 1.0000011, z: 1.000001}
|
||||
- name: RestOfFingers_Intermediate_Right
|
||||
parentName: RestOfFingers_Proximal_Right
|
||||
position: {x: -8.7804575, y: 1.3120176e-14, z: -2.045785e-15}
|
||||
rotation: {x: -0.0000000018626449, y: -0.029668696, z: 0.000000023981553, w: 0.9995598}
|
||||
scale: {x: 0.99999976, y: 1.0000007, z: 1.0000006}
|
||||
- name: Index_Proximal_Right
|
||||
parentName: Hand_Right
|
||||
position: {x: -16.9013, y: -5.4614235e-14, z: -10.104266}
|
||||
rotation: {x: -0.0067928056, y: -0.041411325, z: 0.07197488, w: 0.99652326}
|
||||
scale: {x: 1.0000004, y: 1.0000013, z: 1.0000011}
|
||||
- name: Index_Intermediate_Right
|
||||
parentName: Index_Proximal_Right
|
||||
position: {x: -9.911691, y: 2.0547315e-15, z: -2.2696136e-15}
|
||||
rotation: {x: 0.0000000018626449, y: -0.026280075, z: -0.000000059051665, w: 0.9996546}
|
||||
scale: {x: 0.9999998, y: 1.0000005, z: 1.0000007}
|
||||
- name: Thumb_Proximal_Right
|
||||
parentName: Hand_Right
|
||||
position: {x: -7.0571103, y: -4.7085547, z: -9.280674}
|
||||
rotation: {x: 0.06620055, y: -0.3625544, z: 0.15768987, w: 0.9161364}
|
||||
scale: {x: 1.0000002, y: 1.0000013, z: 1.0000013}
|
||||
- name: Thumb_Intermediate_Right
|
||||
parentName: Thumb_Proximal_Right
|
||||
position: {x: -10.653982, y: 2.4461068e-14, z: 1.7784693e-15}
|
||||
rotation: {x: -0.03195776, y: 0.20743087, z: -0.1379023, w: 0.9679536}
|
||||
scale: {x: 1.0000002, y: 1.0000001, z: 1.0000006}
|
||||
- name: UpperLeg_Left
|
||||
parentName: Hips
|
||||
position: {x: 3.5068195, y: -19.94618, z: -1.3763187}
|
||||
rotation: {x: -0.24868296, y: -0.015556604, z: 0.96813136, w: 0.025227567}
|
||||
scale: {x: 1.0000002, y: 1.0000005, z: 1}
|
||||
- name: LowerLeg_Left
|
||||
parentName: UpperLeg_Left
|
||||
position: {x: -32.81932, y: 2.1316282e-14, z: -8.881784e-15}
|
||||
rotation: {x: -0.000059749553, y: -0.15989013, z: 0.025032664, w: 0.9868174}
|
||||
scale: {x: 1.0000006, y: 1.0000004, z: 1.0000006}
|
||||
- name: Foot_Left
|
||||
parentName: LowerLeg_Left
|
||||
position: {x: -37.066936, y: -1.4210855e-14, z: -4.440892e-15}
|
||||
rotation: {x: 0.13149364, y: 0.6137423, z: -0.22415835, w: 0.74550855}
|
||||
scale: {x: 1.0000005, y: 1, z: 1.0000004}
|
||||
- name: Toe_Left
|
||||
parentName: Foot_Left
|
||||
position: {x: -12.738982, y: -0.5618247, z: 0.30802163}
|
||||
rotation: {x: 0.44987908, y: 0.11339949, z: -0.10218815, w: 0.8799471}
|
||||
scale: {x: 0.9999996, y: 0.9999996, z: 1.0000001}
|
||||
- name: Toetip_Left
|
||||
parentName: Toe_Left
|
||||
position: {x: -17.954567, y: -0.038039967, z: 0.4538383}
|
||||
rotation: {x: 0.04162463, y: 0.030676108, z: -0.003480352, w: 0.9986563}
|
||||
scale: {x: 1.0000002, y: 1.0000002, z: 1.0000006}
|
||||
- name: Shield
|
||||
parentName: Hips
|
||||
position: {x: -36.892387, y: -62.87267, z: 21.847818}
|
||||
rotation: {x: 0.0000000074505797, y: -0.16911028, z: -0.00000008940696, w: 0.98559713}
|
||||
scale: {x: 1.0000004, y: 1.0000006, z: 1}
|
||||
- name: Sword
|
||||
parentName: Hips
|
||||
position: {x: -37.368732, y: 86.23419, z: 18.132149}
|
||||
rotation: {x: 0.0000000074505797, y: -0.16911028, z: -0.00000008940696, w: 0.98559713}
|
||||
scale: {x: 1.0000005, y: 1.0000005, z: 1.0000004}
|
||||
- name: UpperLeg_Right
|
||||
parentName: Hips
|
||||
position: {x: 3.5067785, y: 19.9462, z: -1.3763317}
|
||||
rotation: {x: -0.025228024, y: 0.9681315, z: -0.015552506, w: 0.24868283}
|
||||
scale: {x: 1.0000004, y: 1.0000007, z: 1.0000004}
|
||||
- name: LowerLeg_Right
|
||||
parentName: UpperLeg_Right
|
||||
position: {x: -32.819374, y: -1.0658141e-14, z: -3.5527137e-15}
|
||||
rotation: {x: 0.000059747137, y: 0.15988994, z: 0.025033906, w: 0.9868174}
|
||||
scale: {x: 1.0000005, y: 1.0000004, z: 1.0000013}
|
||||
- name: Foot_Right
|
||||
parentName: LowerLeg_Right
|
||||
position: {x: -37.066925, y: -3.5527137e-15, z: 2.7533531e-14}
|
||||
rotation: {x: -0.09970065, y: -0.6316042, z: -0.16588187, w: 0.75074565}
|
||||
scale: {x: 1.0000006, y: 1.0000006, z: 1.0000011}
|
||||
- name: Toe_Right
|
||||
parentName: Foot_Right
|
||||
position: {x: -12.755086, y: -7.1054274e-15, z: -1.2434498e-14}
|
||||
rotation: {x: -0.4975446, y: -0.111791134, z: -0.10089414, w: 0.85426724}
|
||||
scale: {x: 1.0000005, y: 0.99999994, z: 1.0000006}
|
||||
- name: Toetip_Right
|
||||
parentName: Toe_Right
|
||||
position: {x: -17.96039, y: 0, z: 3.5527137e-15}
|
||||
rotation: {x: -0.05678159, y: -0.018067792, z: -0.0037392974, w: 0.99821615}
|
||||
scale: {x: 1.0000002, y: 0.99999994, z: 1.0000005}
|
||||
armTwist: 0.5
|
||||
foreArmTwist: 0.5
|
||||
upperLegTwist: 0.5
|
||||
legTwist: 0.5
|
||||
armStretch: 0.05
|
||||
legStretch: 0.05
|
||||
feetSpacing: 0
|
||||
globalScale: 1
|
||||
rootMotionBoneName:
|
||||
hasTranslationDoF: 0
|
||||
hasExtraRoot: 1
|
||||
skeletonHasParents: 0
|
||||
lastHumanDescriptionAvatarSource: {instanceID: 0}
|
||||
autoGenerateAvatarMappingIfUnspecified: 1
|
||||
animationType: 2
|
||||
humanoidOversampling: 1
|
||||
avatarSetup: 0
|
||||
addHumanoidExtraRootOnlyWhenUsingAvatar: 0
|
||||
additionalBone: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user