Update samples

This commit is contained in:
hevinci
2022-07-18 14:59:15 +08:00
parent df5f0b9c13
commit 95e6921a4e
357 changed files with 0 additions and 8 deletions

View File

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

View File

@@ -0,0 +1,186 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class PatchCombineWindow : EditorWindow
{
private class DependInfo
{
public string MainBundleName;
public string[] DependBundleNames;
}
static PatchCombineWindow _thisInstance;
[MenuItem("YooAsset/补丁包合并工具", false, 303)]
static void ShowWindow()
{
if (_thisInstance == null)
{
_thisInstance = EditorWindow.GetWindow(typeof(PatchCombineWindow), false, "补丁包合并工具", true) as PatchCombineWindow;
_thisInstance.minSize = new Vector2(800, 600);
}
_thisInstance.Show();
}
private string _patchManifestPath1 = string.Empty;
private string _patchManifestPath2 = string.Empty;
private string _patchManifestSaveFolder = string.Empty;
private readonly Dictionary<PatchAsset, DependInfo> _dependInfos = new Dictionary<PatchAsset, DependInfo>(1000);
private void OnGUI()
{
GUILayout.Space(10);
if (GUILayout.Button("选择保存目录", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFolderPanel("Find", "Assets/", "PatchManifest");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestSaveFolder = resultPath;
}
EditorGUILayout.TextField("合并清单保存目录", _patchManifestSaveFolder);
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包(主)", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestPath1 = resultPath;
}
EditorGUILayout.LabelField(_patchManifestPath1);
EditorGUILayout.EndHorizontal();
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包(副)", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestPath2 = resultPath;
}
EditorGUILayout.LabelField(_patchManifestPath2);
EditorGUILayout.EndHorizontal();
if (string.IsNullOrEmpty(_patchManifestPath1) == false && string.IsNullOrEmpty(_patchManifestPath2) == false)
{
GUILayout.Space(10);
if (GUILayout.Button("合并清单", GUILayout.MaxWidth(150)))
{
CombinePatch();
}
}
}
private void CombinePatch()
{
// 加载补丁清单1
string jsonData1 = FileUtility.ReadFile(_patchManifestPath1);
PatchManifest patchManifest1 = PatchManifest.Deserialize(jsonData1);
// 加载补丁清单1
string jsonData2 = FileUtility.ReadFile(_patchManifestPath2);
PatchManifest patchManifest2 = PatchManifest.Deserialize(jsonData2);
// 检测AssetPath是否冲突
List<string> assetPathList1 = patchManifest1.AssetList.Select(t => t.AssetPath).ToList();
List<string> assetPathList2 = patchManifest2.AssetList.Select(t => t.AssetPath).ToList();
List<string> conflictAssetPathList = assetPathList1.Intersect(assetPathList2).ToList();
if (conflictAssetPathList.Count > 0)
{
foreach (var confictAssetPath in conflictAssetPathList)
{
Debug.LogWarning($"资源路径冲突: {confictAssetPath}");
}
throw new System.Exception("资源路径冲突!请查看警告信息!");
}
// 检测BundleName是否冲突
List<string> bundleNameList1 = patchManifest1.BundleList.Select(t => t.BundleName).ToList();
List<string> bundleNameList2 = patchManifest2.BundleList.Select(t => t.BundleName).ToList();
List<string> conflictBundleNameList = bundleNameList1.Intersect(bundleNameList2).ToList();
if (conflictBundleNameList.Count > 0)
{
foreach (var confictBundleName in conflictBundleNameList)
{
Debug.LogWarning($"资源包名冲突: {confictBundleName}");
}
throw new System.Exception("资源包名冲突!请查看警告信息!");
}
// 记录副资源清单的依赖关系
_dependInfos.Clear();
foreach (var patchAsset in patchManifest2.AssetList)
{
string assetPath = patchAsset.AssetPath;
var mainBundle = patchManifest2.GetMainPatchBundle(assetPath);
var dependBundles = patchManifest2.GetAllDependencies(assetPath);
DependInfo dependInfo = new DependInfo();
dependInfo.MainBundleName = mainBundle.BundleName;
dependInfo.DependBundleNames = dependBundles.Select(t => t.BundleName).ToArray();
_dependInfos.Add(patchAsset, dependInfo);
}
// 副资源清单填充到主资源清单
patchManifest1.AssetList.AddRange(patchManifest2.AssetList);
patchManifest1.BundleList.AddRange(patchManifest2.BundleList);
// 更新填充资源的依赖关系
foreach (var patchAsset in _dependInfos.Keys)
{
patchAsset.BundleID = GetBundleID(patchManifest1, patchAsset);
patchAsset.DependIDs = GetDependIDs(patchManifest1, patchAsset);
}
// 创建合并后的清单文件
string fileSavePath = $"{_patchManifestSaveFolder}/{YooAssetSettingsData.GetPatchManifestFileName(patchManifest1.ResourceVersion)}";
PatchManifest.Serialize(fileSavePath, patchManifest1);
// 创建补丁清单哈希文件
string manifestHashFilePath = $"{_patchManifestSaveFolder}/{YooAssetSettingsData.GetPatchManifestHashFileName(patchManifest1.ResourceVersion)}";
string manifestHash = HashUtility.FileMD5(fileSavePath);
FileUtility.CreateFile(manifestHashFilePath, manifestHash);
Debug.Log("资源清单合并完成!");
}
private int GetBundleID(PatchManifest mainManifest, PatchAsset patchAsset)
{
if (_dependInfos.TryGetValue(patchAsset, out DependInfo dependInfo))
{
int index = mainManifest.BundleList.FindIndex(item => item.BundleName.Equals(dependInfo.MainBundleName));
if (index < 0)
throw new System.Exception("Should never get here !");
return index;
}
else
{
throw new System.Exception("Should never get here !");
}
}
private int[] GetDependIDs(PatchManifest mainManifest, PatchAsset patchAsset)
{
if (_dependInfos.TryGetValue(patchAsset, out DependInfo dependInfo))
{
List<int> results = new List<int>();
foreach (var dependBundleName in dependInfo.DependBundleNames)
{
int index = mainManifest.BundleList.FindIndex(item => item.BundleName.Equals(dependBundleName));
if (index < 0)
throw new System.Exception("Should never get here !");
results.Add(index);
}
return results.ToArray();
}
else
{
throw new System.Exception("Should never get here !");
}
}
}
}

View File

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

View File

@@ -0,0 +1,138 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class PatchCompareWindow : EditorWindow
{
static PatchCompareWindow _thisInstance;
[MenuItem("YooAsset/补丁包比对工具", false, 302)]
static void ShowWindow()
{
if (_thisInstance == null)
{
_thisInstance = EditorWindow.GetWindow(typeof(PatchCompareWindow), false, "补丁包比对工具", true) as PatchCompareWindow;
_thisInstance.minSize = new Vector2(800, 600);
}
_thisInstance.Show();
}
private string _patchManifestPath1 = string.Empty;
private string _patchManifestPath2 = string.Empty;
private readonly List<PatchBundle> _changeList = new List<PatchBundle>();
private readonly List<PatchBundle> _newList = new List<PatchBundle>();
private Vector2 _scrollPos1;
private Vector2 _scrollPos2;
private void OnGUI()
{
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包1", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestPath1 = resultPath;
}
EditorGUILayout.LabelField(_patchManifestPath1);
EditorGUILayout.EndHorizontal();
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包2", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestPath2 = resultPath;
}
EditorGUILayout.LabelField(_patchManifestPath2);
EditorGUILayout.EndHorizontal();
if (string.IsNullOrEmpty(_patchManifestPath1) == false && string.IsNullOrEmpty(_patchManifestPath2) == false)
{
if (GUILayout.Button("比对差异", GUILayout.MaxWidth(150)))
{
ComparePatch(_changeList, _newList);
}
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(false))
{
int totalCount = _changeList.Count;
EditorGUILayout.Foldout(true, $"差异列表 ( {totalCount} )");
EditorGUI.indentLevel = 1;
_scrollPos1 = EditorGUILayout.BeginScrollView(_scrollPos1);
{
foreach (var bundle in _changeList)
{
EditorGUILayout.LabelField($"{bundle.BundleName} | {(bundle.SizeBytes / 1024)}K");
}
}
EditorGUILayout.EndScrollView();
EditorGUI.indentLevel = 0;
}
EditorGUILayout.Space();
using (new EditorGUI.DisabledScope(false))
{
int totalCount = _newList.Count;
EditorGUILayout.Foldout(true, $"新增列表 ( {totalCount} )");
EditorGUI.indentLevel = 1;
_scrollPos2 = EditorGUILayout.BeginScrollView(_scrollPos2);
{
foreach (var bundle in _newList)
{
EditorGUILayout.LabelField($"{bundle.BundleName}");
}
}
EditorGUILayout.EndScrollView();
EditorGUI.indentLevel = 0;
}
}
private void ComparePatch(List<PatchBundle> changeList, List<PatchBundle> newList)
{
changeList.Clear();
newList.Clear();
// 加载补丁清单1
string jsonData1 = FileUtility.ReadFile(_patchManifestPath1);
PatchManifest patchManifest1 = PatchManifest.Deserialize(jsonData1);
// 加载补丁清单1
string jsonData2 = FileUtility.ReadFile(_patchManifestPath2);
PatchManifest patchManifest2 = PatchManifest.Deserialize(jsonData2);
// 拷贝文件列表
foreach (var patchBundle2 in patchManifest2.BundleList)
{
if (patchManifest1.TryGetPatchBundle(patchBundle2.BundleName, out PatchBundle patchBundle1))
{
if (patchBundle2.Hash != patchBundle1.Hash)
{
changeList.Add(patchBundle2);
}
}
else
{
newList.Add(patchBundle2);
}
}
// 按字母重新排序
changeList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName));
newList.Sort((x, y) => string.Compare(x.BundleName, y.BundleName));
Debug.Log("资源包差异比对完成!");
}
}
}

View File

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

View File

@@ -0,0 +1,110 @@
using System.IO;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class PatchImportWindow : EditorWindow
{
static PatchImportWindow _thisInstance;
[MenuItem("YooAsset/补丁包导入工具", false, 301)]
static void ShowWindow()
{
if (_thisInstance == null)
{
_thisInstance = EditorWindow.GetWindow(typeof(PatchImportWindow), false, "补丁包导入工具", true) as PatchImportWindow;
_thisInstance.minSize = new Vector2(800, 600);
}
_thisInstance.Show();
}
private string _patchManifestPath = string.Empty;
private void OnGUI()
{
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择补丁包", GUILayout.MaxWidth(150)))
{
string resultPath = EditorUtility.OpenFilePanel("Find", "Assets/", "bytes");
if (string.IsNullOrEmpty(resultPath))
return;
_patchManifestPath = resultPath;
}
EditorGUILayout.LabelField(_patchManifestPath);
EditorGUILayout.EndHorizontal();
if (string.IsNullOrEmpty(_patchManifestPath) == false)
{
if (GUILayout.Button("导入补丁包(内置文件)", GUILayout.MaxWidth(150)))
{
AssetBundleBuilderHelper.ClearStreamingAssetsFolder();
CopyPatchFiles(_patchManifestPath, false);
}
if (GUILayout.Button("导入补丁包(全部文件)", GUILayout.MaxWidth(150)))
{
AssetBundleBuilderHelper.ClearStreamingAssetsFolder();
CopyPatchFiles(_patchManifestPath, true);
}
}
}
private void CopyPatchFiles(string patchManifestFilePath, bool allPatchFile)
{
string manifestFileName = Path.GetFileNameWithoutExtension(patchManifestFilePath);
string outputDirectory = Path.GetDirectoryName(patchManifestFilePath);
// 加载补丁清单
string jsonData = FileUtility.ReadFile(patchManifestFilePath);
PatchManifest patchManifest = PatchManifest.Deserialize(jsonData);
// 拷贝核心文件
{
string sourcePath = $"{outputDirectory}/{manifestFileName}.bytes";
string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{manifestFileName}.bytes";
EditorTools.CopyFile(sourcePath, destPath, true);
}
{
string sourcePath = $"{outputDirectory}/{manifestFileName}.hash";
string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{manifestFileName}.hash";
EditorTools.CopyFile(sourcePath, destPath, true);
}
{
string sourcePath = $"{outputDirectory}/{YooAssetSettings.VersionFileName}";
string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{YooAssetSettings.VersionFileName}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
// 拷贝文件列表
int fileCount = 0;
if (allPatchFile)
{
foreach (var patchBundle in patchManifest.BundleList)
{
fileCount++;
string sourcePath = $"{outputDirectory}/{patchBundle.Hash}";
string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{patchBundle.Hash}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
}
else
{
foreach (var patchBundle in patchManifest.BundleList)
{
if (patchBundle.IsBuildin == false)
continue;
fileCount++;
string sourcePath = $"{outputDirectory}/{patchBundle.Hash}";
string destPath = $"{AssetBundleBuilderHelper.GetStreamingAssetsFolderPath()}/{patchBundle.Hash}";
EditorTools.CopyFile(sourcePath, destPath, true);
}
}
Debug.Log($"补丁包拷贝完成,一共拷贝了{fileCount}个资源文件");
AssetDatabase.Refresh();
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"name": "YooAsset.EditorExtension",
"rootNamespace": "",
"references": [
"YooAsset",
"YooAsset.Editor"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

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

View File

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

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public static class AssetOperationHandleExtension
{
/*
/// <summary>
/// 获取资源对象
/// </summary>
/// <typeparam name="TAsset"></typeparam>
/// <param name="asset"></param>
public static AssetOperationHandle GetAssetObject<TAsset>(this AssetOperationHandle thisHandle, out TAsset asset) where TAsset : UnityEngine.Object
{
if (thisHandle.Status != EOperationStatus.Succeed)
{
var assetInfo = thisHandle.GetAssetInfo();
Debug.LogWarning($"The {assetInfo.AssetPath}[{assetInfo.AssetType}] is not success. Error[{thisHandle.LastError}]");
}
asset = thisHandle.AssetObject as TAsset;
return thisHandle;
}
*/
/// <summary>
/// 等待异步执行完毕
/// </summary>
public static AssetOperationHandle WaitForAsyncOperationComplete(this AssetOperationHandle thisHandle)
{
thisHandle.WaitForAsyncComplete();
return thisHandle;
}
}

View File

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

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
public class LoadAssetsByTagOperation<TObject> : GameAsyncOperation where TObject : UnityEngine.Object
{
private enum ESteps
{
None,
LoadAssets,
CheckResult,
Done,
}
private readonly string _tag;
private ESteps _steps = ESteps.None;
private List<AssetOperationHandle> _handles;
/// <summary>
/// 资源对象集合
/// </summary>
public List<TObject> AssetObjects { private set; get; }
public LoadAssetsByTagOperation(string tag)
{
_tag = tag;
}
protected override void OnStart()
{
_steps = ESteps.LoadAssets;
}
protected override void OnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
if (_steps == ESteps.LoadAssets)
{
AssetInfo[] assetInfos = YooAssets.GetAssetInfos(_tag);
_handles = new List<AssetOperationHandle>(assetInfos.Length);
foreach (var assetInfo in assetInfos)
{
var handle = YooAssets.LoadAssetAsync(assetInfo);
_handles.Add(handle);
}
_steps = ESteps.CheckResult;
}
if (_steps == ESteps.CheckResult)
{
int index = 0;
foreach (var handle in _handles)
{
if (handle.IsDone == false)
{
Progress = (float)index / _handles.Count;
return;
}
index++;
}
AssetObjects = new List<TObject>(_handles.Count);
foreach (var handle in _handles)
{
if (handle.Status == EOperationStatus.Succeed)
{
var assetObject = handle.AssetObject as TObject;
if (assetObject != null)
{
AssetObjects.Add(assetObject);
}
else
{
string error = $"资源类型转换失败:{handle.AssetObject.name}";
Debug.LogError($"{error}");
AssetObjects.Clear();
SetFinish(false, error);
return;
}
}
else
{
Debug.LogError($"{handle.LastError}");
AssetObjects.Clear();
SetFinish(false, handle.LastError);
return;
}
}
SetFinish(true);
}
}
private void SetFinish(bool succeed, string error = "")
{
Error = error;
Status = succeed ? EOperationStatus.Succeed : EOperationStatus.Failed;
_steps = ESteps.Done;
}
/// <summary>
/// 释放资源句柄
/// </summary>
public void ReleaseHandle()
{
foreach (var handle in _handles)
{
handle.Release();
}
_handles.Clear();
}
}

View File

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