Merge branch 'tuyoogame:main' into main

pull/62/head
Sayo 2023-02-07 11:47:51 +08:00 committed by GitHub
commit fbba2ddec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 249 additions and 101 deletions

View File

@ -12,134 +12,169 @@ namespace YooAsset.Editor
{ {
public static class ShaderVariantCollector public static class ShaderVariantCollector
{ {
private enum ESteps
{
None,
Prepare,
CollectAllMaterial,
CollectVariants,
CollectSleeping,
WaitingDone,
}
private const float WaitMilliseconds = 1000f; private const float WaitMilliseconds = 1000f;
private static string _saveFilePath; private const float SleepMilliseconds = 100f;
private static bool _isStarted = false; private static string _savePath;
private static readonly Stopwatch _elapsedTime = new Stopwatch(); private static string _packageName;
private static int _processMaxNum;
private static Action _completedCallback; private static Action _completedCallback;
private static void EditorUpdate() private static ESteps _steps = ESteps.None;
{ private static Stopwatch _elapsedTime;
// 注意:一定要延迟保存才会起效 private static List<string> _allMaterials;
if (_isStarted && _elapsedTime.ElapsedMilliseconds > WaitMilliseconds) private static List<GameObject> _allSpheres = new List<GameObject>(1000);
{
_isStarted = false;
_elapsedTime.Stop();
EditorApplication.update -= EditorUpdate;
// 保存结果
ShaderVariantCollectionHelper.SaveCurrentShaderVariantCollection(_saveFilePath);
// 创建清单
CreateManifest();
Debug.Log($"搜集SVC完毕");
_completedCallback?.Invoke();
}
}
/// <summary> /// <summary>
/// 开始收集 /// 开始收集
/// </summary> /// </summary>
public static void Run(string saveFilePath, Action completedCallback) public static void Run(string savePath, string packageName, int processMaxNum, Action completedCallback)
{ {
if (_isStarted) if (_steps != ESteps.None)
return; return;
if (Path.HasExtension(saveFilePath) == false) if (Path.HasExtension(savePath) == false)
saveFilePath = $"{saveFilePath}.shadervariants"; savePath = $"{savePath}.shadervariants";
if (Path.GetExtension(saveFilePath) != ".shadervariants") if (Path.GetExtension(savePath) != ".shadervariants")
throw new System.Exception("Shader variant file extension is invalid."); throw new System.Exception("Shader variant file extension is invalid.");
if (string.IsNullOrEmpty(packageName))
throw new System.Exception("Package name is null or empty !");
// 注意先删除再保存否则ShaderVariantCollection内容将无法及时刷新 // 注意先删除再保存否则ShaderVariantCollection内容将无法及时刷新
AssetDatabase.DeleteAsset(ShaderVariantCollectorSettingData.Setting.SavePath); AssetDatabase.DeleteAsset(savePath);
EditorTools.CreateFileDirectory(saveFilePath); EditorTools.CreateFileDirectory(savePath);
_saveFilePath = saveFilePath; _savePath = savePath;
_packageName = packageName;
_processMaxNum = processMaxNum;
_completedCallback = completedCallback; _completedCallback = completedCallback;
// 聚焦到游戏窗口 // 聚焦到游戏窗口
EditorTools.FocusUnityGameWindow(); EditorTools.FocusUnityGameWindow();
// 清空旧数据
ShaderVariantCollectionHelper.ClearCurrentShaderVariantCollection();
// 创建临时测试场景 // 创建临时测试场景
CreateTempScene(); CreateTempScene();
// 收集着色器变种 _steps = ESteps.Prepare;
var materials = GetAllMaterials();
CollectVariants(materials);
EditorApplication.update += EditorUpdate; EditorApplication.update += EditorUpdate;
_isStarted = true;
_elapsedTime.Reset();
_elapsedTime.Start();
} }
private static void EditorUpdate()
{
if (_steps == ESteps.None)
return;
if (_steps == ESteps.Prepare)
{
ShaderVariantCollectionHelper.ClearCurrentShaderVariantCollection();
_steps = ESteps.CollectAllMaterial;
return; //等待一帧
}
if (_steps == ESteps.CollectAllMaterial)
{
_allMaterials = GetAllMaterials();
_steps = ESteps.CollectVariants;
return; //等待一帧
}
if (_steps == ESteps.CollectVariants)
{
int count = Mathf.Min(_processMaxNum, _allMaterials.Count);
List<string> range = _allMaterials.GetRange(0, count);
_allMaterials.RemoveRange(0, count);
CollectVariants(range);
if (_allMaterials.Count > 0)
{
_elapsedTime = Stopwatch.StartNew();
_steps = ESteps.CollectSleeping;
}
else
{
_elapsedTime = Stopwatch.StartNew();
_steps = ESteps.WaitingDone;
}
}
if (_steps == ESteps.CollectSleeping)
{
if (_elapsedTime.ElapsedMilliseconds > SleepMilliseconds)
{
DestroyAllSpheres();
_elapsedTime.Stop();
_steps = ESteps.CollectVariants;
}
}
if (_steps == ESteps.WaitingDone)
{
// 注意:一定要延迟保存才会起效
if (_elapsedTime.ElapsedMilliseconds > WaitMilliseconds)
{
_elapsedTime.Stop();
_steps = ESteps.None;
// 保存结果并创建清单
ShaderVariantCollectionHelper.SaveCurrentShaderVariantCollection(_savePath);
CreateManifest();
Debug.Log($"搜集SVC完毕");
EditorApplication.update -= EditorUpdate;
_completedCallback?.Invoke();
}
}
}
private static void CreateTempScene() private static void CreateTempScene()
{ {
EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
} }
private static List<Material> GetAllMaterials() private static List<string> GetAllMaterials()
{ {
int progressValue = 0; int progressValue = 0;
List<string> allAssets = new List<string>(1000); List<string> allAssets = new List<string>(1000);
// 获取所有打包的资源 // 获取所有打包的资源
List<CollectAssetInfo> allCollectAssetInfos = new List<CollectAssetInfo>(); CollectResult collectResult = AssetBundleCollectorSettingData.Setting.GetPackageAssets(EBuildMode.DryRunBuild, _packageName);
List<CollectResult> collectResults = AssetBundleCollectorSettingData.Setting.GetAllPackageAssets(EBuildMode.DryRunBuild); foreach (var assetInfo in collectResult.CollectAssets)
foreach (var collectResult in collectResults)
{ {
allCollectAssetInfos.AddRange(collectResult.CollectAssets); string[] depends = AssetDatabase.GetDependencies(assetInfo.AssetPath, true);
foreach (var dependAsset in depends)
{
if (allAssets.Contains(dependAsset) == false)
allAssets.Add(dependAsset);
} }
List<string> allAssetPath = allCollectAssetInfos.Select(t => t.AssetPath).ToList(); EditorTools.DisplayProgressBar("获取所有打包资源", ++progressValue, collectResult.CollectAssets.Count);
foreach (var assetPath in allAssetPath)
{
string[] depends = AssetDatabase.GetDependencies(assetPath, true);
foreach (var depend in depends)
{
if (allAssets.Contains(depend) == false)
allAssets.Add(depend);
}
EditorTools.DisplayProgressBar("获取所有打包资源", ++progressValue, allAssetPath.Count);
} }
EditorTools.ClearProgressBar(); EditorTools.ClearProgressBar();
// 搜集所有材质球 // 搜集所有材质球
progressValue = 0; progressValue = 0;
var shaderDic = new Dictionary<Shader, List<Material>>(100); List<string> allMaterial = new List<string>(1000);
foreach (var assetPath in allAssets) foreach (var assetPath in allAssets)
{ {
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath); System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Material)) if (assetType == typeof(UnityEngine.Material))
{ {
var material = AssetDatabase.LoadAssetAtPath<Material>(assetPath); allMaterial.Add(assetPath);
var shader = material.shader;
if (shader == null)
continue;
if (shaderDic.ContainsKey(shader) == false)
{
shaderDic.Add(shader, new List<Material>());
}
if (shaderDic[shader].Contains(material) == false)
{
shaderDic[shader].Add(material);
}
} }
EditorTools.DisplayProgressBar("搜集所有材质球", ++progressValue, allAssets.Count); EditorTools.DisplayProgressBar("搜集所有材质球", ++progressValue, allAssets.Count);
} }
EditorTools.ClearProgressBar(); EditorTools.ClearProgressBar();
// 返回结果 // 返回结果
var materials = new List<Material>(1000); return allMaterial;
foreach (var valuePair in shaderDic)
{
materials.AddRange(valuePair.Value);
} }
return materials; private static void CollectVariants(List<string> materials)
}
private static void CollectVariants(List<Material> materials)
{ {
Camera camera = Camera.main; Camera camera = Camera.main;
if (camera == null) if (camera == null)
@ -164,7 +199,9 @@ namespace YooAsset.Editor
{ {
var material = materials[i]; var material = materials[i];
var position = new Vector3(x - halfWidth + 1f, y - halfHeight + 1f, 0f); var position = new Vector3(x - halfWidth + 1f, y - halfHeight + 1f, 0f);
CreateSphere(material, position, i); var go = CreateSphere(material, position, i);
if (go != null)
_allSpheres.Add(go);
if (x == xMax) if (x == xMax)
{ {
x = 0; x = 0;
@ -174,27 +211,44 @@ namespace YooAsset.Editor
{ {
x++; x++;
} }
EditorTools.DisplayProgressBar("测试所有材质球", ++progressValue, materials.Count); EditorTools.DisplayProgressBar("照射所有材质球", ++progressValue, materials.Count);
} }
EditorTools.ClearProgressBar(); EditorTools.ClearProgressBar();
} }
private static void CreateSphere(Material material, Vector3 position, int index) private static GameObject CreateSphere(string assetPath, Vector3 position, int index)
{ {
var material = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
var shader = material.shader;
if (shader == null)
return null;
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere); var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.GetComponent<Renderer>().material = material; go.GetComponent<Renderer>().sharedMaterial = material;
go.transform.position = position; go.transform.position = position;
go.name = $"Sphere_{index} | {material.name}"; go.name = $"Sphere_{index} | {material.name}";
return go;
}
private static void DestroyAllSpheres()
{
foreach(var go in _allSpheres)
{
GameObject.DestroyImmediate(go);
}
_allSpheres.Clear();
// 尝试释放编辑器加载的资源
EditorUtility.UnloadUnusedAssetsImmediate(true);
} }
private static void CreateManifest() private static void CreateManifest()
{ {
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
ShaderVariantCollection svc = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(_saveFilePath); ShaderVariantCollection svc = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(_savePath);
if (svc != null) if (svc != null)
{ {
var wrapper = ShaderVariantCollectionManifest.Extract(svc); var wrapper = ShaderVariantCollectionManifest.Extract(svc);
string jsonData = JsonUtility.ToJson(wrapper, true); string jsonData = JsonUtility.ToJson(wrapper, true);
string savePath = _saveFilePath.Replace(".shadervariants", ".json"); string savePath = _savePath.Replace(".shadervariants", ".json");
File.WriteAllText(savePath, jsonData); File.WriteAllText(savePath, jsonData);
} }

View File

@ -8,5 +8,10 @@ namespace YooAsset.Editor
/// 文件存储路径 /// 文件存储路径
/// </summary> /// </summary>
public string SavePath = "Assets/MyShaderVariants.shadervariants"; public string SavePath = "Assets/MyShaderVariants.shadervariants";
/// <summary>
/// 收集的包裹名称
/// </summary>
public string CollectPackage = string.Empty;
} }
} }

View File

@ -18,10 +18,13 @@ namespace YooAsset.Editor
window.minSize = new Vector2(800, 600); window.minSize = new Vector2(800, 600);
} }
private List<string> _packageNames;
private Button _collectButton; private Button _collectButton;
private TextField _collectOutputField; private TextField _collectOutputField;
private Label _currentShaderCountField; private Label _currentShaderCountField;
private Label _currentVariantCountField; private Label _currentVariantCountField;
private PopupField<string> _packageField;
public void CreateGUI() public void CreateGUI()
{ {
@ -36,6 +39,9 @@ namespace YooAsset.Editor
visualAsset.CloneTree(root); visualAsset.CloneTree(root);
// 包裹名称列表
_packageNames = GetBuildPackageNames();
// 文件输出目录 // 文件输出目录
_collectOutputField = root.Q<TextField>("CollectOutput"); _collectOutputField = root.Q<TextField>("CollectOutput");
_collectOutputField.SetValueWithoutNotify(ShaderVariantCollectorSettingData.Setting.SavePath); _collectOutputField.SetValueWithoutNotify(ShaderVariantCollectorSettingData.Setting.SavePath);
@ -44,14 +50,34 @@ namespace YooAsset.Editor
ShaderVariantCollectorSettingData.Setting.SavePath = _collectOutputField.value; ShaderVariantCollectorSettingData.Setting.SavePath = _collectOutputField.value;
}); });
// 收集的包裹
var packageContainer = root.Q("PackageContainer");
if (_packageNames.Count > 0)
{
int defaultIndex = GetDefaultPackageIndex(ShaderVariantCollectorSettingData.Setting.CollectPackage);
_packageField = new PopupField<string>(_packageNames, defaultIndex);
_packageField.label = "Package";
_packageField.style.width = 350;
_packageField.RegisterValueChangedCallback(evt =>
{
ShaderVariantCollectorSettingData.Setting.CollectPackage = _packageField.value;
});
packageContainer.Add(_packageField);
}
else
{
_packageField = new PopupField<string>();
_packageField.label = "Package";
_packageField.style.width = 350;
packageContainer.Add(_packageField);
}
_currentShaderCountField = root.Q<Label>("CurrentShaderCount"); _currentShaderCountField = root.Q<Label>("CurrentShaderCount");
_currentVariantCountField = root.Q<Label>("CurrentVariantCount"); _currentVariantCountField = root.Q<Label>("CurrentVariantCount");
// 变种收集按钮 // 变种收集按钮
_collectButton = root.Q<Button>("CollectButton"); _collectButton = root.Q<Button>("CollectButton");
_collectButton.clicked += CollectButton_clicked; _collectButton.clicked += CollectButton_clicked;
//RefreshWindow();
} }
catch (Exception e) catch (Exception e)
{ {
@ -75,7 +101,33 @@ namespace YooAsset.Editor
private void CollectButton_clicked() private void CollectButton_clicked()
{ {
ShaderVariantCollector.Run(ShaderVariantCollectorSettingData.Setting.SavePath, null); string savePath = ShaderVariantCollectorSettingData.Setting.SavePath;
string packageName = ShaderVariantCollectorSettingData.Setting.CollectPackage;
ShaderVariantCollector.Run(savePath, packageName, int.MaxValue, null);
}
// 构建包裹相关
private int GetDefaultPackageIndex(string packageName)
{
for (int index = 0; index < _packageNames.Count; index++)
{
if (_packageNames[index] == packageName)
{
return index;
}
}
ShaderVariantCollectorSettingData.Setting.CollectPackage = _packageNames[0];
return 0;
}
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
} }
} }
} }

View File

@ -1,9 +1,10 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True"> <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;" /> <uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;" />
<ui:VisualElement name="BuildContainer"> <ui:VisualElement name="CollectContainer">
<ui:TextField picking-mode="Ignore" label="文件保存路径" name="CollectOutput" /> <ui:TextField picking-mode="Ignore" label="文件保存路径" name="CollectOutput" style="height: 22px;" />
<ui:Label text="Current Shader Count" display-tooltip-when-elided="true" name="CurrentShaderCount" /> <ui:VisualElement name="PackageContainer" style="height: 24px;" />
<ui:Label text="Current Variant Count" display-tooltip-when-elided="true" name="CurrentVariantCount" /> <ui:Label text="Current Shader Count" display-tooltip-when-elided="true" name="CurrentShaderCount" style="height: 20px; padding-left: 4px;" />
<ui:Label text="Current Variant Count" display-tooltip-when-elided="true" name="CurrentVariantCount" style="height: 20px; padding-left: 4px;" />
<ui:Button text="开始搜集" display-tooltip-when-elided="true" name="CollectButton" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" /> <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:VisualElement>
</ui:UXML> </ui:UXML>

View File

@ -48,7 +48,7 @@ namespace YooAsset
result.TotalSize += (ulong)dependBundle.MainBundleInfo.Bundle.FileSize; result.TotalSize += (ulong)dependBundle.MainBundleInfo.Bundle.FileSize;
result.DownloadedBytes += dependBundle.DownloadedBytes; result.DownloadedBytes += dependBundle.DownloadedBytes;
} }
result.Progress = result.DownloadedBytes / result.TotalSize; result.Progress = (float)result.DownloadedBytes / result.TotalSize;
return result; return result;
} }

View File

@ -228,7 +228,7 @@ namespace YooAsset
List<OperationHandleBase> tempers = new List<OperationHandleBase>(_handles); List<OperationHandleBase> tempers = new List<OperationHandleBase>(_handles);
foreach (var hande in tempers) foreach (var hande in tempers)
{ {
if (hande.IsValidWithWarning) if (hande.IsValid)
{ {
hande.InvokeCallback(); hande.InvokeCallback();
} }

View File

@ -7,6 +7,8 @@ namespace YooAsset
internal class OperationSystem internal class OperationSystem
{ {
private static readonly List<AsyncOperationBase> _operations = new List<AsyncOperationBase>(100); private static readonly List<AsyncOperationBase> _operations = new List<AsyncOperationBase>(100);
private static readonly List<AsyncOperationBase> _addList = new List<AsyncOperationBase>(100);
private static readonly List<AsyncOperationBase> _removeList = new List<AsyncOperationBase>(100);
// 计时器相关 // 计时器相关
private static Stopwatch _watch; private static Stopwatch _watch;
@ -44,19 +46,40 @@ namespace YooAsset
{ {
_frameTime = _watch.ElapsedMilliseconds; _frameTime = _watch.ElapsedMilliseconds;
for (int i = _operations.Count - 1; i >= 0; i--) // 添加新的异步操作
if (_addList.Count > 0)
{
for (int i = 0; i < _addList.Count; i++)
{
var operation = _addList[i];
_operations.Add(operation);
}
_addList.Clear();
}
// 更新所有的异步操作
foreach (var operation in _operations)
{ {
if (IsBusy) if (IsBusy)
return; return;
var operation = _operations[i];
operation.Update(); operation.Update();
if (operation.IsDone) if (operation.IsDone)
{ {
_operations.RemoveAt(i); _removeList.Add(operation);
operation.Finish(); operation.Finish();
} }
} }
// 移除已经完成的异步操作
if (_removeList.Count > 0)
{
foreach (var operation in _removeList)
{
_operations.Remove(operation);
}
_removeList.Clear();
}
} }
/// <summary> /// <summary>
@ -65,6 +88,8 @@ namespace YooAsset
public static void DestroyAll() public static void DestroyAll()
{ {
_operations.Clear(); _operations.Clear();
_addList.Clear();
_removeList.Clear();
_watch = null; _watch = null;
_frameTime = 0; _frameTime = 0;
MaxTimeSlice = long.MaxValue; MaxTimeSlice = long.MaxValue;
@ -73,10 +98,10 @@ namespace YooAsset
/// <summary> /// <summary>
/// 开始处理异步操作类 /// 开始处理异步操作类
/// </summary> /// </summary>
public static void StartOperation(AsyncOperationBase operationBase) public static void StartOperation(AsyncOperationBase operation)
{ {
_operations.Add(operationBase); _addList.Add(operation);
operationBase.Start(); operation.Start();
} }
} }
} }

View File

@ -8,7 +8,7 @@ namespace YooAsset
/// <summary> /// <summary>
/// AssetBundle文件的后缀名 /// AssetBundle文件的后缀名
/// </summary> /// </summary>
public string AssetBundleFileVariant = "bundle"; public string BundleFileVariant = "bundle";
/// <summary> /// <summary>
/// 原生文件的后缀名 /// 原生文件的后缀名
@ -42,6 +42,17 @@ namespace YooAsset
public const string PatchManifestFileVersion = "1.4.0"; public const string PatchManifestFileVersion = "1.4.0";
/// <summary>
/// 缓存的数据文件名称
/// </summary>
public const string CacheBundleDataFileName = "__data";
/// <summary>
/// 缓存的信息文件名称
/// </summary>
public const string CacheBundleInfoFileName = "__info";
/// <summary> /// <summary>
/// 构建输出文件夹名称 /// 构建输出文件夹名称
/// </summary> /// </summary>
@ -66,6 +77,6 @@ namespace YooAsset
/// <summary> /// <summary>
/// 忽略的文件类型 /// 忽略的文件类型
/// </summary> /// </summary>
public static readonly string[] IgnoreFileExtensions = { "", ".so", ".dll", ".cs", ".js", ".boo", ".meta", ".cginc" }; public static readonly string[] IgnoreFileExtensions = { "", ".so", ".dll", ".cs", ".js", ".boo", ".meta", ".cginc", ".hlsl" };
} }
} }

View File

@ -79,9 +79,9 @@ namespace YooAsset
{ {
string shareBundleName; string shareBundleName;
if (uniqueBundleName) if (uniqueBundleName)
shareBundleName = $"{packageName.ToLower()}_{YooAssetSettings.UnityShadersBundleName}.{Setting.AssetBundleFileVariant}"; shareBundleName = $"{packageName.ToLower()}_{YooAssetSettings.UnityShadersBundleName}.{Setting.BundleFileVariant}";
else else
shareBundleName = $"{YooAssetSettings.UnityShadersBundleName}.{Setting.AssetBundleFileVariant}"; shareBundleName = $"{YooAssetSettings.UnityShadersBundleName}.{Setting.BundleFileVariant}";
return shareBundleName.ToLower(); return shareBundleName.ToLower();
} }
} }