Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: additional performance improvements #482

Merged
merged 1 commit into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 0 additions & 3 deletions Editor/API/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
55 changes: 44 additions & 11 deletions Editor/API/Serialization/AssetSaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<GeneratedAssets>();
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<GeneratedAssets>();
AssetDatabase.CreateAsset(_rootAsset, rootAssetPath);
_currentSubContainer = CreateAssetContainer();

_assetCount = 0;
}

public void SaveAsset(UnityEngine.Object? obj)
Expand Down