From 528c574077ecfe74e3eb926c669afbed9726da85 Mon Sep 17 00:00:00 2001 From: bd_ Date: Thu, 28 Nov 2024 16:26:43 -0800 Subject: [PATCH] perf: additional performance improvements --- CHANGELOG.md | 13 +----- Editor/API/BuildContext.cs | 3 -- Editor/API/Serialization/AssetSaver.cs | 55 ++++++++++++++++++++------ 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 981a389..bf8976a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,20 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- [#472] [#474] Added the `DependsOnContext` attribute, for declaring dependencies between extension contexts. -- [#473] Added `BuildContext.SetEnableUVDistributionRecalculation` to allow opting out from the automatic call to - `Mesh.RecalculateUVDistributionMetrics` on generated meshes. -- [#478] Added `ProfilerScope` API -- [#481] Added `NDMFPreview.GetOriginalObjectForProxy` -- [#480] Added `IExtensionContext.Owner` API. Setting this property will allow errors to be correctly attributed to the - plugin that contains an extension context. -- [#479] Added `IAssetSaver` and `SerializationScope` APIs. - - NDMF plugins are encouraged to use `IAssetSaver.SaveAsset` instead of directly accessing `AssetContainer`. This will - split saved assets across multiple files, to avoid performance degradation as the number of assets in a container - grows. ### Fixed -- [#479] Unpacking generated asset containers can break inter-asset references +- [#482] Additional performance improvements ### Changed diff --git a/Editor/API/BuildContext.cs b/Editor/API/BuildContext.cs index 3aacdc1..3898dcd 100644 --- a/Editor/API/BuildContext.cs +++ b/Editor/API/BuildContext.cs @@ -129,9 +129,6 @@ public BuildContext(GameObject obj, string assetRootPath, bool isClone = true) if (assetRootPath != null) { - // Ensure the target directory exists - Directory.CreateDirectory(assetRootPath); - AssetSaver = new AssetSaver(assetRootPath, avatarName); } else diff --git a/Editor/API/Serialization/AssetSaver.cs b/Editor/API/Serialization/AssetSaver.cs index abacc7e..e2eb902 100644 --- a/Editor/API/Serialization/AssetSaver.cs +++ b/Editor/API/Serialization/AssetSaver.cs @@ -38,22 +38,55 @@ internal AssetSaver(string generatedAssetsRoot, string avatarName, int assetsPer if (AssetDatabase.IsValidFolder(subAssetPath)) { + using var _2 = new ProfilerScope("DeleteFolder"); AssetDatabase.DeleteAsset(rootPath); } + + using var _ = new ProfilerScope("Asset editing"); + try + { + AssetDatabase.StartAssetEditing(); + + // Ensure directory exists recursively + var pathParts = subAssetPath.Split('/'); + var currentDir = pathParts[0]; + + for (int i = 1; i < pathParts.Length; i++) + { + var nextDir = currentDir + "/" + pathParts[i]; + if (!AssetDatabase.IsValidFolder(nextDir)) + { + if (Directory.Exists(nextDir)) + { + // Sometimes the asset database can be unaware of a folder on disk, so refresh it. + // This is quite expensive, so only do it if necessary. + Debug.Log("Force refresh due to " + nextDir); + using var _2 = new ProfilerScope("AssetDatabase.Refresh"); + AssetDatabase.Refresh(); + } + else + { + using var _2 = new ProfilerScope("CreateFolder"); + AssetDatabase.CreateFolder(currentDir, pathParts[i]); + } + } + + currentDir = nextDir; + } + + var rootAssetPath = AssetDatabase.GenerateUniqueAssetPath(rootPath + "/" + avatarName + ".asset"); + _rootAsset = ScriptableObject.CreateInstance(); + AssetDatabase.CreateAsset(_rootAsset, rootAssetPath); + _currentSubContainer = CreateAssetContainer(); - // Ensure directory exists recursively - if (!AssetDatabase.IsValidFolder(subAssetPath)) + _assetCount = 0; + } + finally { - Directory.CreateDirectory(subAssetPath); - AssetDatabase.Refresh(); + using var _2 = new ProfilerScope("StopAssetEditing"); + + AssetDatabase.StopAssetEditing(); } - - var rootAssetPath = AssetDatabase.GenerateUniqueAssetPath(rootPath + "/" + avatarName + ".asset"); - _rootAsset = ScriptableObject.CreateInstance(); - AssetDatabase.CreateAsset(_rootAsset, rootAssetPath); - _currentSubContainer = CreateAssetContainer(); - - _assetCount = 0; } public void SaveAsset(UnityEngine.Object? obj)