From 580b2db11250c93a5bc811381e39d3efb7970525 Mon Sep 17 00:00:00 2001
From: Unity Technologies <@unity>
Date: Wed, 26 Jun 2024 00:00:00 +0000
Subject: [PATCH] com.unity.addressables@2.2.2 ## [2.2.2] - 2024-06-26 - Fix
KeyNotFoundException when clicking on local bundles in the profiler. - Fix
bundles incorrectly marked as released in the Profiler when they are still
active - Improved error message when trying to load a catalog in an
unexpected file format. - Fixed issue where operation that uses
WaitForCompletion can timeout much earlier than it should. - The build
scripts were reworked so that you can extend them or copy them outside the
package without having to fork the entire package. - A Version field was
added to the Addressables object for getting the package version in the
Editor. - Fixed an issue where tearing down the Addressables instance could
happen before user tear down code was getting called. - Sort collections to
make serialized editor files deterministic - Fixed issue where labels on an
addressable sub-entry are incorrectly added to the former parent entry. -
Added support for calling Release() on AsyncOperationHandles directly that
couldn't before. - Fixed sub-object loading from AssetReferences for types
that are not Sprites in a SpriteAtlas.
---
CHANGELOG.md | 18 +-
Documentation~/DownloadDependenciesAsync.md | 2 +
Editor/Build/AddressableAnalytics.cs | 2 +-
Editor/Build/AddressablesDataBuilderInput.cs | 6 +-
Editor/Build/AddressablesDataBuilders.cs | 2 +-
.../BuildLayoutGenerationTask.cs | 28 +-
Editor/Build/ContentUpdateScript.cs | 10 +-
.../AddressableAssetsBuildContext.cs | 64 +-
.../DataBuilders/BuildLayoutParameters.cs | 47 +
.../BuildLayoutParameters.cs.meta | 3 +
Editor/Build/DataBuilders/BuildScriptBase.cs | 137 +-
.../DataBuilders/BuildScriptPackedMode.cs | 235 ++--
.../Build/FastModeInitializationOperation.cs | 2 +-
Editor/Build/Layout/BuildLayout.cs | 4 +-
.../AddressablesProfilerDetailsView.cs | 99 +-
.../Profiler/BuildLayoutsManager.cs | 35 +-
.../Profiler/EditorFrameDataStore.cs | 26 +
.../Profiler/EditorFrameDataStore.cs.meta | 3 +
.../Diagnostics/Profiler/FrameDataViewRef.cs | 24 +
.../Profiler/FrameDataViewRef.cs.meta | 3 +
.../Diagnostics/Profiler/IFrameDataStore.cs | 13 +
.../Profiler/IFrameDataStore.cs.meta | 3 +
Editor/GUI/AssetInspectorGUI.cs | 16 +-
Editor/Settings/AddressableAssetEntry.cs | 8 +-
Editor/Settings/AddressableAssetSettings.cs | 28 +-
Runtime/Addressables.cs | 31 +-
Runtime/AddressablesImpl.cs | 120 +-
Runtime/AssetReference.cs | 4 +-
.../Initialization/CheckCatalogsOperation.cs | 2 +-
.../InitializationObjectsOperation.cs | 2 +-
.../Initialization/InitializationOperation.cs | 24 +-
.../Initialization/UpdateCatalogsOperation.cs | 4 +-
.../ResourceLocators/ContentCatalogData.cs | 14 +-
.../AsyncOperations/AsyncOperationBase.cs | 4 +-
.../AsyncOperations/AsyncOperationHandle.cs | 37 +-
.../AsyncOperations/ProviderOperation.cs | 2 -
.../Diagnostics/Profiling/EngineEmitter.cs | 24 +
.../Profiling/EngineEmitter.cs.meta | 3 +
.../Diagnostics/Profiling/IProfilerEmitter.cs | 12 +
.../Profiling/IProfilerEmitter.cs.meta | 3 +
.../Diagnostics/Profiling/ProfilerRuntime.cs | 22 +-
Runtime/ResourceManager/ResourceManager.cs | 13 +
.../ResourceProviders/AssetBundleProvider.cs | 20 +-
.../ResourceProviders/AtlasSpriteProvider.cs | 8 +
.../ResourceProviders/InstanceProvider.cs | 6 +-
.../ResourceProviders/SceneProvider.cs | 28 +-
.../Simulation/VirtualAssetBundle.cs | 4 +-
.../ResourceProviders/TextDataProvider.cs | 43 +-
.../Util/ComponentSingleton.cs | 3 +-
.../ResourceManager/Util/ListWithEvents.cs | 6 +-
.../ContentCatalogProvider.cs | 22 +-
.../AddressablesUtility.cs | 6 +-
.../ComponentReference/ComponentReference.cs | 2 +-
.../Editor/CustomBuild.asset | 2 +-
.../Editor/CustomBuild.asset.meta | 2 +-
.../Editor/CustomBuildScript.cs | 1204 +----------------
.../Editor/CustomBuildScript.cs.meta | 2 +-
.../Editor/CustomPlayMode.asset | 2 +-
.../Editor/CustomPlayMode.asset.meta | 2 +-
.../Editor/CustomPlayModeScript.cs | 79 +-
.../Editor/CustomPlayModeScript.cs.meta | 2 +-
Samples~/PrefabSpawner/PrefabSpawnerSample.cs | 4 +-
Samples~/Tests/SamplesTests.cs | 4 +-
Tests/Editor/AddressableAssetEntryTests.cs | 124 ++
.../AddressableAssetFolderSubfolderTests.cs | 2 +-
Tests/Editor/BinaryStorageBufferTests.cs | 3 +-
Tests/Editor/Build/BuildScriptPackedTests.cs | 20 +-
.../Editor/Build/VerifyPublicBuildScripts.cs | 89 ++
.../Build/VerifyPublicBuildScripts.cs.meta | 11 +
Tests/Editor/Diagnostics/Profiler.meta | 7 +-
.../AddressablesProfilerDetailsViewTests.cs | 182 ++-
.../Profiler/BuildLayoutBuilder.cs | 114 ++
.../Profiler/BuildLayoutBuilder.cs.meta | 3 +
.../Profiler/ProfilerEventBuilder.cs | 244 ++++
.../Profiler/ProfilerEventBuilder.cs.meta | 3 +
.../Diagnostics/Profiler/TestProfiler.cs | 124 ++
.../Diagnostics/Profiler/TestProfiler.cs.meta | 3 +
.../DocExampleCode/AsynchronousLoading.cs | 2 +-
Tests/Editor/DocExampleCode/LoadLocation.cs | 4 +-
Tests/Editor/DocExampleCode/LoadMultiple.cs | 2 +-
Tests/Editor/DocExampleCode/LoadSingle.cs | 2 +-
.../DocExampleCode/LoadSynchronously.cs | 4 +-
.../Editor/DocExampleCode/LoadWithAddress.cs | 2 +-
Tests/Editor/DocExampleCode/LoadWithEvent.cs | 4 +-
.../DocExampleCode/LoadWithIEnumerator.cs | 4 +-
Tests/Editor/DocExampleCode/LoadWithLabels.cs | 2 +-
Tests/Editor/DocExampleCode/LoadWithTask.cs | 2 +-
.../DocExampleCode/MiscellaneousTopics.cs | 10 +-
.../DocExampleCode/PreloadWithProgress.cs | 2 +-
.../ScriptReference/ContentBuiltCheck.cs | 2 +
.../ScriptReference/UsingCleanBundleCache.cs | 4 +-
.../ScriptReference/UsingInitializeAsync.cs | 2 +-
.../ScriptReference/UsingInstanceProvider.cs | 4 +-
.../ScriptReference/UsingInstantiateAsync.cs | 4 +-
.../UsingInternalIdTransformFunc.cs | 2 +-
.../ScriptReference/UsingLoadAssetAsync.cs | 6 +-
...ssables.Editor.Tests.DocExampleCode.asmdef | 55 +
...es.Editor.Tests.DocExampleCode.asmdef.meta | 7 +
Tests/Editor/Fixtures/buildlayout1.json | 2 +
Tests/Editor/Fixtures/buildlayout1.json.meta | 7 +
.../Editor/OptionalPackages/Diagnostics.meta | 3 -
.../Diagnostics/Profiler.meta | 3 -
.../AddressablesProfilerDetailsViewTests.cs | 99 --
Tests/Editor/SerializationTests.cs | 6 +-
Tests/Runtime/AddressablesIntegrationTests.cs | 10 +
.../AddressablesIntegrationTestsImpl.cs | 255 +++-
Tests/Runtime/AddressablesTestFixture.cs | 6 +-
Tests/Runtime/AddressablesTestUtilities.cs | 28 +-
Tests/Runtime/AssetReferenceDrawerTests.cs | 2 +-
Tests/Runtime/DynamicContentUpdateTests.cs | 18 +-
.../Operations/AsyncOperationHandleTests.cs | 124 ++
.../Operations/BaseOperationBehaviorTests.cs | 65 +-
.../ResourceManager/ResourceManagerTests.cs | 5 +-
Tests/Runtime/SceneTests.cs | 105 +-
Tests/Runtime/SyncAddressableTests.cs | 6 +-
package.json | 12 +-
116 files changed, 2438 insertions(+), 1963 deletions(-)
create mode 100644 Editor/Build/DataBuilders/BuildLayoutParameters.cs
create mode 100644 Editor/Build/DataBuilders/BuildLayoutParameters.cs.meta
create mode 100644 Editor/Diagnostics/Profiler/EditorFrameDataStore.cs
create mode 100644 Editor/Diagnostics/Profiler/EditorFrameDataStore.cs.meta
create mode 100644 Editor/Diagnostics/Profiler/FrameDataViewRef.cs
create mode 100644 Editor/Diagnostics/Profiler/FrameDataViewRef.cs.meta
create mode 100644 Editor/Diagnostics/Profiler/IFrameDataStore.cs
create mode 100644 Editor/Diagnostics/Profiler/IFrameDataStore.cs.meta
create mode 100644 Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs
create mode 100644 Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs.meta
create mode 100644 Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs
create mode 100644 Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs.meta
create mode 100644 Tests/Editor/Build/VerifyPublicBuildScripts.cs
create mode 100644 Tests/Editor/Build/VerifyPublicBuildScripts.cs.meta
create mode 100644 Tests/Editor/Diagnostics/Profiler/BuildLayoutBuilder.cs
create mode 100644 Tests/Editor/Diagnostics/Profiler/BuildLayoutBuilder.cs.meta
create mode 100644 Tests/Editor/Diagnostics/Profiler/ProfilerEventBuilder.cs
create mode 100644 Tests/Editor/Diagnostics/Profiler/ProfilerEventBuilder.cs.meta
create mode 100644 Tests/Editor/Diagnostics/Profiler/TestProfiler.cs
create mode 100644 Tests/Editor/Diagnostics/Profiler/TestProfiler.cs.meta
create mode 100644 Tests/Editor/DocExampleCode/Unity.Addressables.Editor.Tests.DocExampleCode.asmdef
create mode 100644 Tests/Editor/DocExampleCode/Unity.Addressables.Editor.Tests.DocExampleCode.asmdef.meta
create mode 100644 Tests/Editor/Fixtures/buildlayout1.json
create mode 100644 Tests/Editor/Fixtures/buildlayout1.json.meta
delete mode 100644 Tests/Editor/OptionalPackages/Diagnostics.meta
delete mode 100644 Tests/Editor/OptionalPackages/Diagnostics/Profiler.meta
delete mode 100644 Tests/Editor/OptionalPackages/Diagnostics/Profiler/AddressablesProfilerDetailsViewTests.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 43a13110..f1186f5d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,10 +4,24 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+## [2.2.2] - 2024-06-26
+- Fix KeyNotFoundException when clicking on local bundles in the profiler.
+- Fix bundles incorrectly marked as released in the Profiler when they are still active
+- Improved error message when trying to load a catalog in an unexpected file format.
+- Fixed issue where operation that uses WaitForCompletion can timeout much earlier than it should.
+- The build scripts were reworked so that you can extend them or copy them outside the package without having to fork the entire package.
+- A Version field was added to the Addressables object for getting the package version in the Editor.
+- Fixed an issue where tearing down the Addressables instance could happen before user tear down code was getting called.
+- Sort collections to make serialized editor files deterministic
+- Fixed issue where labels on an addressable sub-entry are incorrectly added to the former parent entry.
+- Added support for calling Release() on AsyncOperationHandles directly that couldn't before.
+- Fixed sub-object loading from AssetReferences for types that are not Sprites in a SpriteAtlas.
+
+
## [2.1.0] - 2024-03-19
- Fix "Unable to verify target bucket for Remote Catalog: Not Found. Object could not be found" error
- Fixed caching to prevent unnecessary refreshing of bucket data.
-- Sort collections on serialization to prevent unecessary merge conflicts
+- Sort collections on serialization to prevent unnecessary merge conflicts
- Add warnings and documentation to make it clear you need to release the handle from LoadDependenciesAsync
## [2.0.8] - 2024-01-19
@@ -63,6 +77,8 @@ CCD Manager is built when using the Build to CCD and the standard Build content
- Fixed an issue where "Failed to remove scene from Addressables profiler" warning occurs when a scene is unloaded.
- Fixed an exception getting thrown in the Addressables Report when drilling into a bundle chain
- Fixed string deduplication in binary catalogs. Certain data sets were causing data to expand.
+- Removed the Analyze Rule API and corresponding tool
+- Removed the Event Viewer API and corresponding tool
## [1.21.18] - 2023-09-23
- Fixed an issue where scene InternalId collisions were very likely when using dynamic internal asset naming
diff --git a/Documentation~/DownloadDependenciesAsync.md b/Documentation~/DownloadDependenciesAsync.md
index 7f141d1c..bc0e3fd1 100644
--- a/Documentation~/DownloadDependenciesAsync.md
+++ b/Documentation~/DownloadDependenciesAsync.md
@@ -36,6 +36,8 @@ Always release the download operation handle after you have read the `Result` ob
[!code-cs[sample](../Tests/Editor/DocExampleCode/Preload.cs#doc_Preload)]
+To note: On the WebGL platform, this API always returns the size of the AssetBundle, even if the AssetBundle has been cached. Cached AssetBundles are not stored on the local file system, but persisted as part of the IndexedDB of the browser. [WebGL Caching](https://docs.unity3d.com/Manual/webgl-caching.html)
+
### Clear the dependency cache
If you want to clear any AssetBundles cached by Addressables, call [`Addressables.ClearDependencyCacheAsync`](xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*). This method clears the cached AssetBundles containing the assets identified by a key along with any bundles containing those assets' dependencies.
diff --git a/Editor/Build/AddressableAnalytics.cs b/Editor/Build/AddressableAnalytics.cs
index 9215e586..dc0bf8e8 100644
--- a/Editor/Build/AddressableAnalytics.cs
+++ b/Editor/Build/AddressableAnalytics.cs
@@ -467,7 +467,7 @@ internal static BuildData GenerateBuildData(AddressablesDataBuilderInput builder
if (selected == -1)
pathType = PathType.Custom;
else
- pathType = prefixToTypeMap[groupTypes[selected].GroupTypePrefix];
+ pathType = prefixToTypeMap.GetValueOrDefault(groupTypes[selected].GroupTypePrefix, PathType.Custom);
if (pathType == PathType.Custom)
{
diff --git a/Editor/Build/AddressablesDataBuilderInput.cs b/Editor/Build/AddressablesDataBuilderInput.cs
index c014748d..e83a2f41 100644
--- a/Editor/Build/AddressablesDataBuilderInput.cs
+++ b/Editor/Build/AddressablesDataBuilderInput.cs
@@ -34,8 +34,10 @@ public class AddressablesDataBuilderInput
///
public FileRegistry Registry { get; private set; }
- //used only by tests to inject custom info into build...
- internal string PathSuffix = string.Empty;
+ ///
+ /// can be used in testing to append a suffix to file paths
+ ///
+ public string PathSuffix = string.Empty;
///
/// The name of the default Runtime Settings file.
diff --git a/Editor/Build/AddressablesDataBuilders.cs b/Editor/Build/AddressablesDataBuilders.cs
index 3005b1a8..76599178 100644
--- a/Editor/Build/AddressablesDataBuilders.cs
+++ b/Editor/Build/AddressablesDataBuilders.cs
@@ -118,7 +118,7 @@ public class BundleBuildResult
///
/// True if the build was doing an update to a previous build, else false.
///
- public bool IsUpdateContentBuild { get; internal set; }
+ public bool IsUpdateContentBuild { get; set; }
///
/// Build results for AssetBundles created during the build.
diff --git a/Editor/Build/BuildPipelineTasks/BuildLayoutGenerationTask.cs b/Editor/Build/BuildPipelineTasks/BuildLayoutGenerationTask.cs
index 7603f2a5..c46c11f3 100644
--- a/Editor/Build/BuildPipelineTasks/BuildLayoutGenerationTask.cs
+++ b/Editor/Build/BuildPipelineTasks/BuildLayoutGenerationTask.cs
@@ -38,12 +38,13 @@ public int Version
}
///
- /// The mapping of the old to new bundle names.
+ /// The mapping of the old to new bundle names. Instead of using this directly inject
+ /// the value through IBuildLayoutParUse BuildLayoutParameters.BundleNameRemap instead
///
public Dictionary BundleNameRemap
{
- get { return m_BundleNameRemap; }
- set { m_BundleNameRemap = value; }
+ get { return m_BuildLayoutParameters.BundleNameRemap; }
+ set { m_BuildLayoutParameters.BundleNameRemap = value; }
}
#pragma warning disable 649
@@ -70,11 +71,12 @@ public int Version
[InjectContext(ContextUsage.In)]
IBundleBuildResults m_BuildBundleResults;
+
+ [InjectContext(ContextUsage.In)]
+ IBuildLayoutParameters m_BuildLayoutParameters;
#pragma warning restore 649
- internal Dictionary m_BundleNameRemap;
internal AddressablesDataBuilderInput m_AddressablesInput;
- internal ContentCatalogData m_ContentCatalogData;
private bool IsContentUpdateBuild => m_AddressablesInput != null && m_AddressablesInput.PreviousContentState != null;
@@ -693,14 +695,14 @@ private BuildLayout GenerateBuildLayout(AddressableAssetsBuildContext aaContext,
layout.RemoteCatalogBuildPath = aaContext.Settings.RemoteCatalogBuildPath.GetValue(aaContext.Settings);
AddressableAssetSettings aaSettings = aaContext.Settings;
- if (m_ContentCatalogData != null)
- layout.BuildResultHash = m_ContentCatalogData.m_BuildResultHash;
+ if (m_BuildLayoutParameters.BuildResultHash != null)
+ layout.BuildResultHash = m_BuildLayoutParameters.BuildResultHash;
using (m_Log.ScopedStep(LogLevel.Info, "Generate Basic Information"))
{
SetLayoutMetaData(layout, aaSettings);
layout.AddressablesEditorSettings = GetAddressableEditorSettings(aaSettings);
- layout.AddressablesRuntimeSettings = GetAddressableRuntimeSettings(aaContext, m_ContentCatalogData);
+ layout.AddressablesRuntimeSettings = GetAddressableRuntimeSettings(aaContext);
}
if (IsContentUpdateBuild)
@@ -847,7 +849,7 @@ void CorrelateBundleToAssetGroup(BuildLayout layout, BuildLayout.Bundle b, Layou
if (aaContext.bundleToAssetGroup.TryGetValue(b.Name, out var grpName))
{
var assetGroup = lookup.GroupLookup[grpName];
- b.Name = m_BundleNameRemap[b.Name];
+ b.Name = m_BuildLayoutParameters.BundleNameRemap[b.Name];
b.Group = assetGroup;
lookup.FilenameToBundle[b.Name] = b;
var filePath = Path.Combine(lookup.GroupNameToBuildPath[assetGroup.Name], b.Name);
@@ -862,7 +864,7 @@ void CorrelateBundleToAssetGroup(BuildLayout layout, BuildLayout.Bundle b, Layou
{
// bundleToAssetGroup doesn't contain the builtin bundles. The builtin content is built using values from the default group
AddressableAssetGroup defaultGroup = aaContext.Settings.DefaultGroup;
- b.Name = m_BundleNameRemap[b.Name];
+ b.Name = m_BuildLayoutParameters.BundleNameRemap[b.Name];
b.Group = lookup.GroupLookup[defaultGroup.Guid]; // should this be set?
lookup.FilenameToBundle[b.Name] = b;
@@ -1161,7 +1163,7 @@ private static void SetLayoutMetaData(BuildLayout layoutOut, AddressableAssetSet
layoutOut.PlayerBuildVersion = aaSettings.PlayerBuildVersion;
}
- static BuildLayout.AddressablesRuntimeData GetAddressableRuntimeSettings(AddressableAssetsBuildContext aaContext, ContentCatalogData contentCatalog)
+ BuildLayout.AddressablesRuntimeData GetAddressableRuntimeSettings(AddressableAssetsBuildContext aaContext)
{
if (aaContext.runtimeData == null)
{
@@ -1175,8 +1177,8 @@ static BuildLayout.AddressablesRuntimeData GetAddressableRuntimeSettings(Address
runtimeSettings.CatalogLoadPaths = new List();
foreach (ResourceLocationData catalogLocation in aaContext.runtimeData.CatalogLocations)
runtimeSettings.CatalogLoadPaths.Add(catalogLocation.InternalId);
- if (contentCatalog != null)
- runtimeSettings.CatalogHash = contentCatalog.localHash;
+ if (m_BuildLayoutParameters.CatalogHash != null)
+ runtimeSettings.CatalogHash = m_BuildLayoutParameters.CatalogHash;
return runtimeSettings;
}
diff --git a/Editor/Build/ContentUpdateScript.cs b/Editor/Build/ContentUpdateScript.cs
index 211e5fd9..0d30bf40 100644
--- a/Editor/Build/ContentUpdateScript.cs
+++ b/Editor/Build/ContentUpdateScript.cs
@@ -371,7 +371,7 @@ static bool HasAssetOrDependencyChanged(CachedAssetState cachedInfo)
/// The server path (if any) that contains an updateable content catalog. If this is empty, updates cannot occur.
/// Cached state that needs to carry over from the previous build. This mainly affects Content Update.
/// True if the file is saved, false otherwise.
- internal static bool SaveContentState(List locations, Dictionary> guidToCatalogLocation, string path, List entries, IDependencyData dependencyData, string playerVersion,
+ public static bool SaveContentState(List locations, Dictionary> guidToCatalogLocation, string path, List entries, IDependencyData dependencyData, string playerVersion,
string remoteCatalogPath, List carryOverCacheState)
{
try
@@ -477,7 +477,13 @@ public static string GetContentStateDataPath(bool browse)
return GetContentStateDataPath(browse, null);
}
- internal static string GetContentStateDataPath(bool browse, AddressableAssetSettings settings)
+ ///
+ /// Gets the path of the cache data from a selected build.
+ ///
+ /// If true, the user is allowed to browse for a specific file.
+ /// The settings object to use for the build.
+ /// The path of the previous state .bin file used to detect changes from the previous build to the content update build.
+ public static string GetContentStateDataPath(bool browse, AddressableAssetSettings settings)
{
if (settings == null)
settings = AddressableAssetSettingsDefaultObject.Settings;
diff --git a/Editor/Build/DataBuilders/AddressableAssetsBuildContext.cs b/Editor/Build/DataBuilders/AddressableAssetsBuildContext.cs
index cdba7af6..c74a71b3 100644
--- a/Editor/Build/DataBuilders/AddressableAssetsBuildContext.cs
+++ b/Editor/Build/DataBuilders/AddressableAssetsBuildContext.cs
@@ -94,68 +94,6 @@ public AddressableAssetSettings Settings
///
/// A mapping of Asset GUID's to resulting ContentCatalogDataEntry entries.
///
- internal Dictionary> GuidToCatalogLocation = null;
-
- private Dictionary> m_PrimaryKeyToDependers = null;
-
- internal Dictionary> PrimaryKeyToDependerLocations
- {
- get
- {
- if (m_PrimaryKeyToDependers != null)
- return m_PrimaryKeyToDependers;
- if (locations == null || locations.Count == 0)
- {
- Debug.LogError("Attempting to get Entries dependent on key, but currently no locations");
- return new Dictionary>(0);
- }
-
- m_PrimaryKeyToDependers = new Dictionary>(locations.Count);
- foreach (ContentCatalogDataEntry location in locations)
- {
- for (int i = 0; i < location.Dependencies.Count; ++i)
- {
- string dependencyKey = location.Dependencies[i] as string;
- if (string.IsNullOrEmpty(dependencyKey))
- continue;
-
- if (!m_PrimaryKeyToDependers.TryGetValue(dependencyKey, out var dependers))
- {
- dependers = new List();
- m_PrimaryKeyToDependers.Add(dependencyKey, dependers);
- }
-
- dependers.Add(location);
- }
- }
-
- return m_PrimaryKeyToDependers;
- }
- }
-
- private Dictionary m_PrimaryKeyToLocation = null;
-
- internal Dictionary PrimaryKeyToLocation
- {
- get
- {
- if (m_PrimaryKeyToLocation != null)
- return m_PrimaryKeyToLocation;
- if (locations == null || locations.Count == 0)
- {
- Debug.LogError("Attempting to get Primary key to entries dependent on key, but currently no locations");
- return new Dictionary();
- }
-
- m_PrimaryKeyToLocation = new Dictionary();
- foreach (var loc in locations)
- {
- if (loc != null && loc.Keys[0] != null && loc.Keys[0] is string && !m_PrimaryKeyToLocation.ContainsKey((string)loc.Keys[0]))
- m_PrimaryKeyToLocation[(string)loc.Keys[0]] = loc;
- }
-
- return m_PrimaryKeyToLocation;
- }
- }
+ public Dictionary> GuidToCatalogLocation = null;
}
}
diff --git a/Editor/Build/DataBuilders/BuildLayoutParameters.cs b/Editor/Build/DataBuilders/BuildLayoutParameters.cs
new file mode 100644
index 00000000..afefd610
--- /dev/null
+++ b/Editor/Build/DataBuilders/BuildLayoutParameters.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using UnityEditor.Build.Pipeline.Interfaces;
+using UnityEngine.AddressableAssets.ResourceLocators;
+
+namespace UnityEditor.AddressableAssets.Build.DataBuilders
+{
+ public interface IBuildLayoutParameters : IContextObject
+ {
+ Dictionary BundleNameRemap { get; set; }
+
+ string BuildResultHash { get; }
+
+ string CatalogHash { get; }
+ }
+
+ public class BuildLayoutParameters : IBuildLayoutParameters
+ {
+ private Dictionary m_BundleNameRemap;
+ private ContentCatalogData m_contentCatalogData;
+
+ public BuildLayoutParameters(Dictionary bundleNameRemap)
+ {
+ m_BundleNameRemap = bundleNameRemap;
+ }
+
+ public BuildLayoutParameters(Dictionary bundleNameRemap, ContentCatalogData contentCatalogData)
+ {
+ m_BundleNameRemap = bundleNameRemap;
+ m_contentCatalogData = contentCatalogData;
+ }
+ public Dictionary BundleNameRemap
+ {
+ get => m_BundleNameRemap;
+ set => m_BundleNameRemap = value;
+ }
+
+ public string BuildResultHash
+ {
+ get => m_contentCatalogData?.BuildResultHash;
+ }
+
+ public string CatalogHash
+ {
+ get => m_contentCatalogData?.LocalHash;
+ }
+ }
+}
diff --git a/Editor/Build/DataBuilders/BuildLayoutParameters.cs.meta b/Editor/Build/DataBuilders/BuildLayoutParameters.cs.meta
new file mode 100644
index 00000000..d5022b4d
--- /dev/null
+++ b/Editor/Build/DataBuilders/BuildLayoutParameters.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5813cc79f668462b91d624cc6fec9ae3
+timeCreated: 1713381856
\ No newline at end of file
diff --git a/Editor/Build/DataBuilders/BuildScriptBase.cs b/Editor/Build/DataBuilders/BuildScriptBase.cs
index 052bd34e..b6324a90 100644
--- a/Editor/Build/DataBuilders/BuildScriptBase.cs
+++ b/Editor/Build/DataBuilders/BuildScriptBase.cs
@@ -2,10 +2,14 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+#if UNITY_2022_2_OR_NEWER
+using UnityEditor.AddressableAssets.BuildReportVisualizer;
+#endif
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
using UnityEditor.Build.Pipeline.Interfaces;
using UnityEditor.Build.Pipeline.Utilities;
+using UnityEditor.Experimental;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.Initialization;
@@ -13,6 +17,8 @@
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.ResourceManagement.Util;
using UnityEngine.Serialization;
+using System.Reflection;
+
namespace UnityEditor.AddressableAssets.Build.DataBuilders
{
@@ -21,6 +27,9 @@ namespace UnityEditor.AddressableAssets.Build.DataBuilders
///
public class BuildScriptBase : ScriptableObject, IDataBuilder
{
+ ///
+ /// Static part of the builtin bundle filename.
+ ///
public const string BuiltInBundleBaseName = "_unitybuiltinassets";
///
@@ -28,14 +37,14 @@ public class BuildScriptBase : ScriptableObject, IDataBuilder
///
[FormerlySerializedAs("m_InstanceProviderType")]
[SerializedTypeRestrictionAttribute(type = typeof(IInstanceProvider))]
- public SerializedType instanceProviderType = new SerializedType() {Value = typeof(InstanceProvider)};
+ public SerializedType instanceProviderType = new SerializedType() { Value = typeof(InstanceProvider) };
///
/// The type of scene provider to create for the addressables system.
///
[FormerlySerializedAs("m_SceneProviderType")]
[SerializedTypeRestrictionAttribute(type = typeof(ISceneProvider))]
- public SerializedType sceneProviderType = new SerializedType() {Value = typeof(SceneProvider)};
+ public SerializedType sceneProviderType = new SerializedType() { Value = typeof(SceneProvider) };
///
/// Stores the logged information of all the build tasks.
@@ -155,6 +164,12 @@ protected virtual string ProcessAllGroups(AddressableAssetsBuildContext aaContex
if (assetGroup == null)
continue;
+ var error = ErrorCheckBundleSettings(assetGroup, aaContext);
+ if (error != string.Empty)
+ {
+ return error;
+ }
+
EditorUtility.DisplayProgressBar($"Processing Addressable Group", assetGroup.Name, (float)index / aaContext.Settings.groups.Count);
var errorString = ProcessGroup(assetGroup, aaContext);
if (!string.IsNullOrEmpty(errorString))
@@ -171,6 +186,47 @@ protected virtual string ProcessAllGroups(AddressableAssetsBuildContext aaContex
return string.Empty;
}
+
+ internal static string ErrorCheckBundleSettings(AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
+ {
+ if (!assetGroup.HasSchema())
+ return string.Empty;
+
+ var message = string.Empty;
+ var settings = aaContext.Settings;
+ var schema = assetGroup.GetSchema();
+
+ string buildPath = settings.profileSettings.GetValueById(settings.activeProfileId, schema.BuildPath.Id);
+ string loadPath = settings.profileSettings.GetValueById(settings.activeProfileId, schema.LoadPath.Id);
+
+ bool buildLocal = AddressableAssetUtility.StringContains(buildPath, "[UnityEngine.AddressableAssets.Addressables.BuildPath]", StringComparison.Ordinal);
+ bool loadLocal = AddressableAssetUtility.StringContains(loadPath, "{UnityEngine.AddressableAssets.Addressables.RuntimePath}", StringComparison.Ordinal);
+
+ if (buildLocal && !loadLocal)
+ {
+ message = "BuildPath for group '" + assetGroup.Name + "' is set to the dynamic-lookup version of StreamingAssets, but LoadPath is not. \n";
+ }
+ else if (!buildLocal && loadLocal)
+ {
+ message = "LoadPath for group " + assetGroup.Name +
+ " is set to the dynamic-lookup version of StreamingAssets, but BuildPath is not. These paths must both use the dynamic-lookup, or both not use it. \n";
+ }
+
+ if (!string.IsNullOrEmpty(message))
+ {
+ message += "BuildPath: '" + buildPath + "'\n";
+ message += "LoadPath: '" + loadPath + "'";
+ }
+
+ if (schema.Compression == BundledAssetGroupSchema.BundleCompressionMode.LZMA && (buildLocal || loadLocal))
+ {
+ Debug.LogWarningFormat("Bundle compression is set to LZMA, but group {0} uses local content.", assetGroup.Name);
+ }
+
+ return message;
+ }
+
+
///
/// Build processing of an individual group.
///
@@ -276,5 +332,82 @@ public virtual bool IsDataBuilt()
{
return false;
}
+
+
+ ///
+ /// Copies the content state binary file from the temp directory to its final location and registers it in the
+ /// file registry and build results.
+ ///
+ /// Temporary location of the content state file.
+ /// Destination location of the content state file.
+ /// The builderInput object used in the build.
+ /// The build data result.
+ public virtual void CopyAndRegisterContentState(string tempPath, string contentStatePath, AddressablesDataBuilderInput builderInput, AddressablesPlayerBuildResult addrResult)
+ {
+ try
+ {
+ string directory = Path.GetDirectoryName(contentStatePath);
+ if (!Directory.Exists(directory))
+ Directory.CreateDirectory(directory);
+ if (File.Exists(contentStatePath))
+ File.Delete(contentStatePath);
+
+ File.Copy(tempPath, contentStatePath, true);
+ if (addrResult != null)
+ addrResult.ContentStateFilePath = contentStatePath;
+ builderInput.Registry.AddFile(contentStatePath);
+ }
+ catch (UnauthorizedAccessException uae)
+ {
+ if (!AddressableAssetUtility.IsVCAssetOpenForEdit(contentStatePath))
+ Debug.LogErrorFormat("Cannot access the file {0}. It may be locked by version control.",
+ contentStatePath);
+ else
+ Debug.LogException(uae);
+ }
+ catch (Exception e)
+ {
+ Debug.LogException(e);
+ }
+ }
+
+ ///
+ /// Notifies the user about the existence of the Addressables Report
+ ///
+ protected virtual void NotifyUserAboutBuildReport()
+ {
+ bool buildReportSettingCheck = ProjectConfigData.UserHasBeenInformedAboutBuildReportSettingPreBuild;
+ if (!buildReportSettingCheck && !Application.isBatchMode && !ProjectConfigData.GenerateBuildLayout)
+ {
+ bool turnOnBuildLayout = EditorUtility.DisplayDialog("Addressables Build Report",
+ "There's a new Addressables Build Report you can check out after your content build. " +
+ "However, this requires that 'Debug Build Layout' is turned on. The setting can be found in Edit > Preferences > Addressables. Would you like to turn it on?",
+ "Yes", "No");
+ if (turnOnBuildLayout)
+ ProjectConfigData.GenerateBuildLayout = true;
+ ProjectConfigData.UserHasBeenInformedAboutBuildReportSettingPreBuild = true;
+ }
+ }
+
+ ///
+ /// Displays the Addressables Report window
+ ///
+ protected virtual void DisplayBuildReport()
+ {
+ if (!Application.isBatchMode && ProjectConfigData.AutoOpenAddressablesReport && ProjectConfigData.GenerateBuildLayout)
+ {
+ BuildReportWindow.ShowWindowAfterBuild();
+ }
+ }
+
+ ///
+ /// Clears content update notifications from teh groups window
+ ///
+ /// A list of groups that were built
+ protected virtual void ClearContentUpdateNotifications(List groups)
+ {
+ foreach (var group in groups)
+ ContentUpdateScript.ClearContentUpdateNotifications(group);
+ }
}
}
diff --git a/Editor/Build/DataBuilders/BuildScriptPackedMode.cs b/Editor/Build/DataBuilders/BuildScriptPackedMode.cs
index 2cfdee98..2abbcf99 100644
--- a/Editor/Build/DataBuilders/BuildScriptPackedMode.cs
+++ b/Editor/Build/DataBuilders/BuildScriptPackedMode.cs
@@ -50,6 +50,60 @@ public override string Name
internal List ResourceProviderData => m_ResourceProviderData.ToList();
+ private Dictionary> m_PrimaryKeyToDependers = null;
+ private Dictionary m_PrimaryKeyToLocation = null;
+ private Dictionary> GetPrimaryKeyToDependerLocations(List locations)
+ {
+ if (m_PrimaryKeyToDependers != null)
+ return m_PrimaryKeyToDependers;
+ if (locations == null || locations.Count == 0)
+ {
+ Debug.LogError("Attempting to get Entries dependent on key, but currently no locations");
+ return new Dictionary>(0);
+ }
+
+ m_PrimaryKeyToDependers = new Dictionary>(locations.Count);
+ foreach (ContentCatalogDataEntry location in locations)
+ {
+ for (int i = 0; i < location.Dependencies.Count; ++i)
+ {
+ string dependencyKey = location.Dependencies[i] as string;
+ if (string.IsNullOrEmpty(dependencyKey))
+ continue;
+
+ if (!m_PrimaryKeyToDependers.TryGetValue(dependencyKey, out var dependers))
+ {
+ dependers = new List();
+ m_PrimaryKeyToDependers.Add(dependencyKey, dependers);
+ }
+
+ dependers.Add(location);
+ }
+ }
+
+ return m_PrimaryKeyToDependers;
+ }
+
+ private Dictionary GetPrimaryKeyToLocation(List locations)
+ {
+ if (m_PrimaryKeyToLocation != null)
+ return m_PrimaryKeyToLocation;
+ if (locations == null || locations.Count == 0)
+ {
+ Debug.LogError("Attempting to get Primary key to entries dependent on key, but currently no locations");
+ return new Dictionary();
+ }
+
+ m_PrimaryKeyToLocation = new Dictionary();
+ foreach (var loc in locations)
+ {
+ if (loc != null && loc.Keys[0] != null && loc.Keys[0] is string && !m_PrimaryKeyToLocation.ContainsKey((string)loc.Keys[0]))
+ m_PrimaryKeyToLocation[(string)loc.Keys[0]] = loc;
+ }
+
+ return m_PrimaryKeyToLocation;
+ }
+
///
public override bool CanBuildData()
{
@@ -59,22 +113,15 @@ public override bool CanBuildData()
///
protected override TResult BuildDataImplementation(AddressablesDataBuilderInput builderInput)
{
- bool buildReportSettingCheck = ProjectConfigData.UserHasBeenInformedAboutBuildReportSettingPreBuild;
- if (!buildReportSettingCheck && !Application.isBatchMode && !ProjectConfigData.GenerateBuildLayout)
- {
- bool turnOnBuildLayout = EditorUtility.DisplayDialog("Addressables Build Report", "There's a new Addressables Build Report you can check out after your content build. " +
- "However, this requires that 'Debug Build Layout' is turned on. The setting can be found in Edit > Preferences > Addressables. Would you like to turn it on?", "Yes", "No");
- if (turnOnBuildLayout)
- ProjectConfigData.GenerateBuildLayout = true;
- ProjectConfigData.UserHasBeenInformedAboutBuildReportSettingPreBuild = true;
- }
+
+ NotifyUserAboutBuildReport();
TResult result = default(TResult);
m_IncludedGroupsInBuild?.Clear();
InitializeBuildContext(builderInput, out AddressableAssetsBuildContext aaContext);
- using (m_Log.ScopedStep(LogLevel.Info, "ProcessAllGroups"))
+ using (Log.ScopedStep(LogLevel.Info, "ProcessAllGroups"))
{
var errorString = ProcessAllGroups(aaContext);
if (!string.IsNullOrEmpty(errorString))
@@ -86,29 +133,16 @@ protected override TResult BuildDataImplementation(AddressablesDataBuil
result = DoBuild(builderInput, aaContext);
}
- if (result != null)
- {
- var span = DateTime.Now - aaContext.buildStartTime;
- result.Duration = span.TotalSeconds;
- }
-
- if (result != null && string.IsNullOrEmpty(result.Error))
- {
- foreach (var group in m_IncludedGroupsInBuild)
- ContentUpdateScript.ClearContentUpdateNotifications(group);
- }
-
- if (result != null && string.IsNullOrEmpty(result.Error))
- {
- foreach (var group in m_IncludedGroupsInBuild)
- ContentUpdateScript.ClearContentUpdateNotifications(group);
- }
+ if (result == null)
+ return result;
- if (result != null && !Application.isBatchMode && ProjectConfigData.AutoOpenAddressablesReport && ProjectConfigData.GenerateBuildLayout)
+ var span = DateTime.Now - aaContext.buildStartTime;
+ result.Duration = span.TotalSeconds;
+ if (string.IsNullOrEmpty(result.Error))
{
- BuildReportWindow.ShowWindowAfterBuild();
+ ClearContentUpdateNotifications(m_IncludedGroupsInBuild);
}
-
+ DisplayBuildReport();
return result;
}
@@ -136,9 +170,11 @@ internal void InitializeBuildContext(AddressablesDataBuilderInput builderInput,
throw;
}
#endif
-
m_AllBundleInputDefs = new List();
m_GroupToBundleNames = new Dictionary();
+ // force these caches to be rebuilt
+ m_PrimaryKeyToDependers = null;
+ m_PrimaryKeyToLocation = null;
var bundleToAssetGroup = new Dictionary();
var runtimeData = new ResourceManagerRuntimeData
{
@@ -153,7 +189,7 @@ internal void InitializeBuildContext(AddressablesDataBuilderInput builderInput,
#if ENABLE_JSON_CATALOG
IsLocalCatalogInBundle = aaSettings.BundleLocalCatalog,
#endif
- AddressablesVersion = PackageManager.PackageInfo.FindForAssembly(typeof(Addressables).Assembly)?.version,
+ AddressablesVersion = Addressables.Version,
MaxConcurrentWebRequests = aaSettings.MaxConcurrentWebRequests,
CatalogRequestsTimeout = aaSettings.CatalogRequestsTimeout
};
@@ -300,11 +336,11 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
buildTasks.Add(extractData);
IBundleBuildResults results;
- using (m_Log.ScopedStep(LogLevel.Info, "ContentPipeline.BuildAssetBundles"))
+ using (Log.ScopedStep(LogLevel.Info, "ContentPipeline.BuildAssetBundles"))
using (new SBPSettingsOverwriterScope(ProjectConfigData.GenerateBuildLayout)) // build layout generation requires full SBP write results
{
var buildContent = new BundleBuildContent(m_AllBundleInputDefs);
- var exitCode = ContentPipeline.BuildAssetBundles(buildParams, buildContent, out results, buildTasks, aaContext, m_Log);
+ var exitCode = ContentPipeline.BuildAssetBundles(buildParams, buildContent, out results, buildTasks, aaContext, Log);
if (exitCode < ReturnCode.Success)
return CreateErrorResult("SBP Error" + exitCode, builderInput, aaContext);
@@ -313,7 +349,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
var groups = aaContext.Settings.groups.Where(g => g != null);
var postCatalogUpdateCallbacks = new List();
- using (m_Log.ScopedStep(LogLevel.Info, "PostProcessBundles"))
+ using (Log.ScopedStep(LogLevel.Info, "PostProcessBundles"))
using (var progressTracker = new UnityEditor.Build.Pipeline.Utilities.ProgressTracker())
{
progressTracker.UpdateTask("Post Processing AssetBundles");
@@ -324,7 +360,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
if (!aaContext.assetGroupToBundles.ContainsKey(assetGroup))
continue;
- using (m_Log.ScopedStep(LogLevel.Info, assetGroup.name))
+ using (Log.ScopedStep(LogLevel.Info, assetGroup.name))
{
PostProcessBundles(assetGroup, results, addrResult,
builderInput.Registry, aaContext,
@@ -333,7 +369,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
}
}
- using (m_Log.ScopedStep(LogLevel.Info, "Process Catalog Entries"))
+ using (Log.ScopedStep(LogLevel.Info, "Process Catalog Entries"))
{
Dictionary locationIdToCatalogEntryMap = BuildLocationIdToCatalogEntryMap(aaContext.locations);
if (builderInput.PreviousContentState != null)
@@ -365,7 +401,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
ContentCatalogData contentCatalog = null;
#if ENABLE_JSON_CATALOG
- using (m_Log.ScopedStep(LogLevel.Info, "Generate JSON Catalog"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate JSON Catalog"))
{
contentCatalog = new ContentCatalogData(ResourceManagerRuntimeData.kCatalogAddress);
@@ -375,7 +411,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
for (int i = 0; i < addrResult.AssetBundleBuildResults.Count; ++i)
hashingObjects[i] = addrResult.AssetBundleBuildResults[i].Hash;
string buildResultHash = HashingMethods.Calculate(hashingObjects).ToString();
- contentCatalog.m_BuildResultHash = buildResultHash;
+ contentCatalog.BuildResultHash = buildResultHash;
}
contentCatalog.SetData(aaContext.locations.OrderBy(f => f.InternalId).ToList());
@@ -390,19 +426,19 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
//save catalog
string contentHash = null;
string jsonText = null;
- using (m_Log.ScopedStep(LogLevel.Info, "Generating Json"))
+ using (Log.ScopedStep(LogLevel.Info, "Generating Json"))
jsonText = JsonUtility.ToJson(contentCatalog);
if (aaContext.Settings.BuildRemoteCatalog || ProjectConfigData.GenerateBuildLayout)
{
- using (m_Log.ScopedStep(LogLevel.Info, "Hashing Catalog"))
+ using (Log.ScopedStep(LogLevel.Info, "Hashing Catalog"))
contentHash = HashingMethods.Calculate(jsonText).ToString();
- contentCatalog.localHash = contentHash;
+ contentCatalog.LocalHash = contentHash;
}
CreateCatalogFiles(jsonText, builderInput, aaContext, contentHash);
}
#else
- using (m_Log.ScopedStep(LogLevel.Info, "Generate Binary Catalog"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate Binary Catalog"))
{
contentCatalog = new ContentCatalogData(ResourceManagerRuntimeData.kCatalogAddress);
@@ -412,7 +448,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
for (int i = 0; i < addrResult.AssetBundleBuildResults.Count; ++i)
hashingObjects[i] = addrResult.AssetBundleBuildResults[i].Hash;
string buildResultHash = HashingMethods.Calculate(hashingObjects).ToString();
- contentCatalog.m_BuildResultHash = buildResultHash;
+ contentCatalog.BuildResultHash = buildResultHash;
}
contentCatalog.ResourceProviderData.AddRange(m_ResourceProviderData);
@@ -427,14 +463,14 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
var contentHash = HashingMethods.Calculate(bytes);
if (aaContext.Settings.BuildRemoteCatalog || ProjectConfigData.GenerateBuildLayout)
- contentCatalog.localHash = contentHash.ToString();
+ contentCatalog.LocalHash = contentHash.ToString();
CreateCatalogFiles(bytes, builderInput, aaContext, contentHash.ToString());
}
#endif
- using (m_Log.ScopedStep(LogLevel.Info, "Generate link"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate link"))
{
foreach (var pd in contentCatalog.ResourceProviderData)
{
@@ -466,20 +502,20 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
var settingsPath = Addressables.BuildPath + "/" + builderInput.RuntimeSettingsFilename;
- using (m_Log.ScopedStep(LogLevel.Info, "Generate Settings"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate Settings"))
WriteFile(settingsPath, JsonUtility.ToJson(aaContext.runtimeData), builderInput.Registry);
if (extractData.BuildCache != null && builderInput.PreviousContentState == null)
{
- using (m_Log.ScopedStep(LogLevel.Info, "Generate Content Update State"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate Content Update State"))
{
var remoteCatalogLoadPath = aaContext.Settings.BuildRemoteCatalog
? aaContext.Settings.RemoteCatalogLoadPath.GetValue(aaContext.Settings)
: string.Empty;
var allEntries = new List();
- using (m_Log.ScopedStep(LogLevel.Info, "Get Assets"))
- aaContext.Settings.GetAllAssets(allEntries, false, ContentUpdateScript.GroupFilter);
+ using (Log.ScopedStep(LogLevel.Info, "Get Assets"))
+ aaContext.Settings.GetAllAssets(allEntries, false, ContentUpdateScript.GroupFilterFunc);
if (ContentUpdateScript.SaveContentState(aaContext.locations, aaContext.GuidToCatalogLocation, tempPath, allEntries,
extractData.DependencyData, playerBuildVersion, remoteCatalogLoadPath,
@@ -495,31 +531,7 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
#endif
}
- try
- {
- string directory = Path.GetDirectoryName(contentStatePath);
- if (!Directory.Exists(directory))
- Directory.CreateDirectory(directory);
- if (File.Exists(contentStatePath))
- File.Delete(contentStatePath);
-
- File.Copy(tempPath, contentStatePath, true);
- if (addrResult != null)
- addrResult.ContentStateFilePath = contentStatePath;
- builderInput.Registry.AddFile(contentStatePath);
- }
- catch (UnauthorizedAccessException uae)
- {
- if (!AddressableAssetUtility.IsVCAssetOpenForEdit(contentStatePath))
- Debug.LogErrorFormat("Cannot access the file {0}. It may be locked by version control.",
- contentStatePath);
- else
- Debug.LogException(uae);
- }
- catch (Exception e)
- {
- Debug.LogException(e);
- }
+ CopyAndRegisterContentState(tempPath, contentStatePath, builderInput, addrResult);
}
}
}
@@ -535,16 +547,13 @@ internal static string GetMonoScriptBundleNamePrefix(AddressableAssetSettings se
using (var progressTracker = new UnityEditor.Build.Pipeline.Utilities.ProgressTracker())
{
progressTracker.UpdateTask("Generating Build Layout");
- using (m_Log.ScopedStep(LogLevel.Info, "Generate Build Layout"))
+ using (Log.ScopedStep(LogLevel.Info, "Generate Build Layout"))
{
List tasks = new List();
var buildLayoutTask = new BuildLayoutGenerationTask();
- buildLayoutTask.m_BundleNameRemap = bundleRenameMap;
- buildLayoutTask.m_ContentCatalogData = contentCatalog;
- if (contentUpdateContext.ContentState != null)
- buildLayoutTask.m_AddressablesInput = builderInput;
+ extractData.BuildContext.SetContextObject(new BuildLayoutParameters(bundleRenameMap, contentCatalog));
tasks.Add(buildLayoutTask);
- BuildTasksRunner.Run(tasks, extractData.m_BuildContext);
+ BuildTasksRunner.Run(tasks, extractData.BuildContext);
}
}
}
@@ -728,7 +737,7 @@ internal ReturnCode CreateCatalogBundle(string filepath, byte[] data, Addressabl
var buildParams = new BundleBuildParameters(builderInput.Target, builderInput.TargetGroup, Path.GetDirectoryName(filepath));
if (builderInput.Target == BuildTarget.WebGL)
buildParams.BundleCompression = BuildCompression.LZ4Runtime;
- var retCode = ContentPipeline.BuildAssetBundles(buildParams, bundleBuildContent, out IBundleBuildResults result, buildTasks, m_Log);
+ var retCode = ContentPipeline.BuildAssetBundles(buildParams, bundleBuildContent, out IBundleBuildResults result, buildTasks, Log);
if (Directory.Exists(tempFolderPath))
{
@@ -846,7 +855,7 @@ internal ReturnCode CreateCatalogBundle(string filepath, string jsonText, Addres
var buildParams = new BundleBuildParameters(builderInput.Target, builderInput.TargetGroup, Path.GetDirectoryName(filepath));
if (builderInput.Target == BuildTarget.WebGL)
buildParams.BundleCompression = BuildCompression.LZ4Runtime;
- var retCode = ContentPipeline.BuildAssetBundles(buildParams, bundleBuildContent, out IBundleBuildResults result, buildTasks, m_Log);
+ var retCode = ContentPipeline.BuildAssetBundles(buildParams, bundleBuildContent, out IBundleBuildResults result, buildTasks, Log);
if (Directory.Exists(tempFolderPath))
{
@@ -1043,10 +1052,6 @@ protected virtual string ProcessGroupSchema(AddressableAssetGroupSchema schema,
if (schema == null || !schema.IncludeInBuild || !assetGroup.entries.Any())
return string.Empty;
- var errorStr = ErrorCheckBundleSettings(schema, assetGroup, aaContext.Settings);
- if (!string.IsNullOrEmpty(errorStr))
- return errorStr;
-
m_IncludedGroupsInBuild?.Add(assetGroup);
AddBundleProvider(schema);
@@ -1118,48 +1123,6 @@ internal static List HandleBundleNames(List bundleInpu
return generatedUniqueNames;
}
- internal static string ErrorCheckBundleSettings(BundledAssetGroupSchema schema, AddressableAssetGroup assetGroup, AddressableAssetSettings settings)
- {
- var message = string.Empty;
-
- string buildPath = schema.BuildPath.GetValue(settings, false);
- if (buildPath == null)
- {
- return "BuildPath for group '" + assetGroup.Name + "' is not set.";
- }
- string loadPath = schema.LoadPath.GetValue(settings, false);
- if (loadPath == null)
- {
- return "LoadPath for group '" + assetGroup.Name + "' is not set.";
- }
-
- bool buildLocal = AddressableAssetUtility.StringContains(buildPath, "[UnityEngine.AddressableAssets.Addressables.BuildPath]", StringComparison.Ordinal);
- bool loadLocal = AddressableAssetUtility.StringContains(loadPath, "{UnityEngine.AddressableAssets.Addressables.RuntimePath}", StringComparison.Ordinal);
-
- if (buildLocal && !loadLocal)
- {
- message = "BuildPath for group '" + assetGroup.Name + "' is set to the dynamic-lookup version of StreamingAssets, but LoadPath is not. \n";
- }
- else if (!buildLocal && loadLocal)
- {
- message = "LoadPath for group " + assetGroup.Name +
- " is set to the dynamic-lookup version of StreamingAssets, but BuildPath is not. These paths must both use the dynamic-lookup, or both not use it. \n";
- }
-
- if (!string.IsNullOrEmpty(message))
- {
- message += "BuildPath: '" + buildPath + "'\n";
- message += "LoadPath: '" + loadPath + "'";
- }
-
- if (schema.Compression == BundledAssetGroupSchema.BundleCompressionMode.LZMA && (buildLocal || loadLocal))
- {
- Debug.LogWarningFormat("Bundle compression is set to LZMA, but group {0} uses local content.", assetGroup.Name);
- }
-
- return message;
- }
-
internal static string CalculateGroupHash(BundledAssetGroupSchema.BundleInternalIdMode mode, AddressableAssetGroup assetGroup, IEnumerable entries)
{
switch (mode)
@@ -1414,7 +1377,7 @@ static void MoveFileToDestinationWithTimestampIfDifferent(string srcPath, string
AddressablesPlayerBuildResult.BundleBuildResult bundleResultInfo = new AddressablesPlayerBuildResult.BundleBuildResult();
bundleResultInfo.SourceAssetGroup = assetGroup;
- if (aaContext.PrimaryKeyToLocation.TryGetValue(builtBundleNames[i], out ContentCatalogDataEntry dataEntry))
+ if (GetPrimaryKeyToLocation(aaContext.locations).TryGetValue(builtBundleNames[i], out ContentCatalogDataEntry dataEntry))
{
var info = buildResult.BundleInfos[builtBundleNames[i]];
bundleResultInfo.Crc = info.Crc;
@@ -1475,7 +1438,7 @@ static void MoveFileToDestinationWithTimestampIfDifferent(string srcPath, string
outputBundleNames[i] = StripHashFromBundleLocation(outputBundleNames[i]);
bundleRenameMap.Add(builtBundleNames[i], outputBundleNames[i]);
- MoveFileToDestinationWithTimestampIfDifferent(srcPath, targetPath, m_Log);
+ MoveFileToDestinationWithTimestampIfDifferent(srcPath, targetPath, Log);
AddPostCatalogUpdatesInternal(assetGroup, postCatalogUpdateCallbacks, dataEntry, targetPath, registry);
if (addrResult != null)
@@ -1572,10 +1535,10 @@ private void SetPrimaryKey(ContentCatalogDataEntry forLocation, string newPrimar
throw new ArgumentException("Invalid primary key for catalog entry " + forLocation.ToString());
forLocation.Keys[0] = newPrimaryKey;
- aaContext.PrimaryKeyToLocation.Remove(originalKey);
- aaContext.PrimaryKeyToLocation.Add(newPrimaryKey, forLocation);
+ m_PrimaryKeyToLocation.Remove(originalKey);
+ m_PrimaryKeyToLocation.Add(newPrimaryKey, forLocation);
- if (!aaContext.PrimaryKeyToDependerLocations.TryGetValue(originalKey, out var dependers))
+ if (!GetPrimaryKeyToDependerLocations(aaContext.locations).TryGetValue(originalKey, out var dependers))
return; // nothing depends on it
foreach (ContentCatalogDataEntry location in dependers)
@@ -1593,8 +1556,8 @@ private void SetPrimaryKey(ContentCatalogDataEntry forLocation, string newPrimar
}
}
- aaContext.PrimaryKeyToDependerLocations.Remove(originalKey);
- aaContext.PrimaryKeyToDependerLocations.Add(newPrimaryKey, dependers);
+ m_PrimaryKeyToDependers.Remove(originalKey);
+ m_PrimaryKeyToDependers.Add(newPrimaryKey, dependers);
}
private static long GetFileSize(string fileName)
diff --git a/Editor/Build/FastModeInitializationOperation.cs b/Editor/Build/FastModeInitializationOperation.cs
index e17b7d81..fb2d5baf 100644
--- a/Editor/Build/FastModeInitializationOperation.cs
+++ b/Editor/Build/FastModeInitializationOperation.cs
@@ -112,7 +112,7 @@ protected override void Execute()
{
bool success = op.Status == AsyncOperationStatus.Succeeded;
Complete(locator, success, success ? "" : $"{op.DebugName}, status={op.Status}, result={op.Result} failed initialization.");
- m_addressables.Release(op);
+ op.Release();
};
}
}
diff --git a/Editor/Build/Layout/BuildLayout.cs b/Editor/Build/Layout/BuildLayout.cs
index 42022125..6d6b4ae4 100644
--- a/Editor/Build/Layout/BuildLayout.cs
+++ b/Editor/Build/Layout/BuildLayout.cs
@@ -242,7 +242,7 @@ public DateTime BuildStart
internal string m_FilePath;
private bool m_HeaderRead = false;
- private bool m_BodyRead = false;
+ internal bool m_BodyRead = false;
private FileStream m_FileStream = null;
private StreamReader m_StreamReader = null;
@@ -1023,7 +1023,7 @@ public ulong UncompressedSize
public List OtherAssets = new List();
///
- /// A list of referenced explicit assets located in other AssetBundles.
+ /// A list of referenced explicit assets located in other AssetBundles.
///
[SerializeReference]
public List ExternalReferences = new List();
diff --git a/Editor/Diagnostics/Profiler/AddressablesProfilerDetailsView.cs b/Editor/Diagnostics/Profiler/AddressablesProfilerDetailsView.cs
index 335010c0..8c80bbfb 100644
--- a/Editor/Diagnostics/Profiler/AddressablesProfilerDetailsView.cs
+++ b/Editor/Diagnostics/Profiler/AddressablesProfilerDetailsView.cs
@@ -24,25 +24,34 @@ internal class AddressablesProfilerDetailsView : IDisposable
private const string k_ViewNonLoadedPreferencesKey = k_PreferencesKeyPrefix + k_ViewNonLoadedActionName;
private const string k_ViewObjectsPreferencesKey = k_PreferencesKeyPrefix + k_ViewObjectsActionName;
- private readonly struct FrameData
+ internal readonly struct FrameData
{
- public readonly NativeArray CatalogValues;
- public readonly NativeArray BundleValues;
- public readonly NativeArray AssetValues;
- public readonly NativeArray SceneValues;
+ public readonly IEnumerable CatalogValues;
+ public readonly IEnumerable BundleValues;
+ public readonly IEnumerable AssetValues;
+ public readonly IEnumerable SceneValues;
- public bool HasValues => CatalogValues.IsCreated && CatalogValues.Length > 0;
+ public bool HasValues
+ {
+ get
+ {
+ if (CatalogValues == null)
+ return false;
+ using var e = CatalogValues.GetEnumerator();
+ return e.MoveNext();
+ }
+ }
public FrameData(int frame)
{
- using (var rawFrameData = UnityEditorInternal.ProfilerDriver.GetRawFrameDataView(frame, 0))
+ using (var rawFrameDataRef = m_frameDataStore.GetRawFrameDataView(frame, 0))
{
- if (rawFrameData != null && rawFrameData.valid)
+ if (rawFrameDataRef != null && rawFrameDataRef.valid)
{
- CatalogValues = rawFrameData.GetFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kCatalogTag);
- BundleValues = rawFrameData.GetFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kBundleDataTag);
- AssetValues = rawFrameData.GetFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kAssetDataTag);
- SceneValues = rawFrameData.GetFrameMetaData(ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kSceneDataTag);
+ CatalogValues = m_frameDataStore.GetFrameMetaData(rawFrameDataRef, ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kCatalogTag);
+ BundleValues = m_frameDataStore.GetFrameMetaData(rawFrameDataRef, ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kBundleDataTag);
+ AssetValues = m_frameDataStore.GetFrameMetaData(rawFrameDataRef, ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kAssetDataTag);
+ SceneValues = m_frameDataStore.GetFrameMetaData(rawFrameDataRef, ProfilerRuntime.kResourceManagerProfilerGuid, ProfilerRuntime.kSceneDataTag);
}
else
{
@@ -59,7 +68,7 @@ public FrameData(int frame)
private ToolbarSearchField m_SearchField;
private ContentSearch m_SearchController = new ContentSearch();
-
+ internal static IFrameDataStore m_frameDataStore = new EditorFrameDataStore();
private AddressablesProfilerDetailsDataInspector m_DetailsInspector;
@@ -86,15 +95,24 @@ public AddressablesProfilerDetailsView(ProfilerWindow profilerWindow)
public VisualElement CreateView()
{
- m_ViewGroups = EditorPrefs.GetBool(k_ViewGroupsPreferencesKey, false);
- m_ViewAssetBundles = EditorPrefs.GetBool(k_ViewAssetBundlesPreferencesKey, true);
- m_ViewAssets = EditorPrefs.GetBool(k_ViewAssetsPreferencesKey, true);
- m_ViewNonLoadedAssets = EditorPrefs.GetBool(k_ViewNonLoadedPreferencesKey, false);
- m_ViewObjects = EditorPrefs.GetBool(k_ViewObjectsPreferencesKey, false);
-
- CreateViewsWithToolbarInLeft();
- OnReinitialise();
- return m_RootSplitView;
+ try
+ {
+ m_ViewGroups = EditorPrefs.GetBool(k_ViewGroupsPreferencesKey, false);
+ m_ViewAssetBundles = EditorPrefs.GetBool(k_ViewAssetBundlesPreferencesKey, true);
+ m_ViewAssets = EditorPrefs.GetBool(k_ViewAssetsPreferencesKey, true);
+ m_ViewNonLoadedAssets = EditorPrefs.GetBool(k_ViewNonLoadedPreferencesKey, false);
+ m_ViewObjects = EditorPrefs.GetBool(k_ViewObjectsPreferencesKey, false);
+
+ CreateViewsWithToolbarInLeft();
+ OnReinitialise();
+ return m_RootSplitView;
+ }
+ catch (Exception e)
+ {
+ // this can be caused by data issues and can be nearly impossible to track down once caught further up
+ Debug.LogException(e);
+ throw;
+ }
}
private VisualElement CreateViewsWithToolbarInLeft()
@@ -213,7 +231,7 @@ void ReloadData(long selectedFrameIndex)
MissingBuildReportDisplay(missingBuildHash);
}
}
- GenerateContentDataForFrame(frameData);
+ m_RootGroupsContentData = GenerateContentDataForFrame(frameData);
BuildTree();
}
else
@@ -411,16 +429,16 @@ private int CompareTreeColumnData(TreeViewItemData x, TreeViewItemD
return 0;
}
- private void GenerateContentDataForFrame(FrameData frameData)
+ internal List GenerateContentDataForFrame(FrameData frameData)
{
Dictionary reportBundleToBundleData = new Dictionary();
List bundleContent = GenerateBundleRoots(frameData.BundleValues, reportBundleToBundleData);
GenerateAssetData(bundleContent, frameData.AssetValues, frameData.SceneValues);
List groupContent = CollectGroups(bundleContent);
- m_RootGroupsContentData = groupContent;
+ return groupContent;
}
- List GenerateBundleRoots(in NativeArray bundleValues, in Dictionary reportBundleToBundleData)
+ List GenerateBundleRoots(in IEnumerable bundleValues, in Dictionary reportBundleToBundleData)
{
List bundleDatas = new List();
foreach (BundleFrameData frameData in bundleValues)
@@ -430,18 +448,21 @@ List GenerateBundleRoots(in NativeArray bundleValue
return new List();
BundleData bundleData = new BundleData(layoutBundle, frameData);
bundleDatas.Add(bundleData);
- reportBundleToBundleData.Add(layoutBundle, bundleData);
+ if (!reportBundleToBundleData.TryAdd(layoutBundle, bundleData))
+ {
+ throw new Exception($"Unable to add bundle data for bundle {layoutBundle.Name}, duplicate data exists.");
+ }
}
GenerateBundleDependencies(bundleDatas, reportBundleToBundleData);
return bundleDatas;
}
- void GenerateAssetData(List bundleDatas, in NativeArray assetValues, in NativeArray sceneValues)
+ internal void GenerateAssetData(List bundleDatas, in IEnumerable assetValues, in IEnumerable sceneValues)
{
Dictionary bundleCodeToData = new Dictionary();
foreach (BundleData data in bundleDatas)
- bundleCodeToData.Add(data.BundleCode, data);
+ bundleCodeToData.TryAdd(data.BundleCode, data);
List addressableLoadedAssets = new List();
// add all addressable loaded assets so later know they are fully loaded
@@ -518,7 +539,7 @@ private AssetData GetAssetDataForFrameData(AssetFrameData frameData, Dictionary<
return assetData;
}
- private void ProcessAssetReferences(List activeAddressableAssets, Dictionary bundleCodeToData)
+ internal void ProcessAssetReferences(List activeAddressableAssets, Dictionary bundleCodeToData)
{
// instead get a stack
Stack assetsToBeProcessed = new Stack(activeAddressableAssets);
@@ -531,7 +552,10 @@ private void ProcessAssetReferences(List activeAddressableAssets, Dic
if(!processedAssets.Add(assetData))
continue; // not needed
- BundleData parentBundle = bundleCodeToData[((BundleData)assetData.Parent).BundleCode];
+ if (!bundleCodeToData.TryGetValue(((BundleData)assetData.Parent).BundleCode, out var parentBundle))
+ {
+ continue;
+ }
foreach (BuildLayout.ObjectData objectData in assetData.ReportObjects)
{
// get or create object for self, this may have already been made from a reference
@@ -557,7 +581,7 @@ private void ProcessAssetReferences(List activeAddressableAssets, Dic
}
}
- private AssetData ProcessReference(AssetData referencingAssetData, ObjectData referencingObjectData,
+ internal AssetData ProcessReference(AssetData referencingAssetData, ObjectData referencingObjectData,
BuildLayout.ObjectReference objectReference, BundleData parentBundle, Dictionary bundleCodeToData)
{
BuildLayout.File file = referencingAssetData.IsImplicit ? referencingAssetData.ReportImplicitData.File : referencingAssetData.ReportExplicitData.File;
@@ -584,7 +608,14 @@ private void ProcessAssetReferences(List activeAddressableAssets, Dic
if (referencedReportAsset.Bundle != bundleContainingReferencedObj.ReportBundle)
{
int bundleCode = referencedReportAsset.Bundle.InternalName.GetHashCode();
- bundleContainingReferencedObj = bundleCodeToData[bundleCode];
+ if (bundleCodeToData.ContainsKey(bundleCode))
+ {
+ bundleContainingReferencedObj = bundleCodeToData[bundleCode];
+ }
+ else
+ {
+ Debug.LogWarning($"Asset {referencedReportAsset.AddressableName} referenced bundle {referencedReportAsset.Bundle.Name} not loaded from build layout, attaching to parent {bundleContainingReferencedObj.ReportBundle.Name}");
+ }
}
bundleContainingReferencedObj.GetOrCreateAssetData(referencedReportAsset, out referencedAssetData);
@@ -628,7 +659,7 @@ private static void GenerateBundleDependencies(List bundleDatas, in
{
foreach (BundleData data in bundleDatas)
{
- foreach (BuildLayout.Bundle dependency in data.ReportBundle.Dependencies)
+ foreach (BuildLayout.Bundle dependency in data.ReportBundle.Dependencies ?? new List())
{
if (!reportBundleToBundleData.TryGetValue(dependency, out var bundleDataIsDependantOn))
continue;
diff --git a/Editor/Diagnostics/Profiler/BuildLayoutsManager.cs b/Editor/Diagnostics/Profiler/BuildLayoutsManager.cs
index 826d3d7d..52c3bb7b 100644
--- a/Editor/Diagnostics/Profiler/BuildLayoutsManager.cs
+++ b/Editor/Diagnostics/Profiler/BuildLayoutsManager.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.IO;
using Unity.Collections;
@@ -23,7 +24,8 @@ public ActiveLayout(BuildLayout layout)
foreach (BuildLayout.Bundle bundle in BuildLayoutHelpers.EnumerateBundles(layout))
{
int bundleCode = bundle.InternalName.GetHashCode();
- m_BundleMap.Add(bundleCode, bundle);
+ if (!m_BundleMap.TryAdd(bundleCode, bundle))
+ throw new Exception($"Duplicate bundle code ${bundle.InternalName.GetHashCode()} found for ${bundle.Name} in layout.");
Dictionary assetMap = new Dictionary(bundle.AssetCount);
foreach (BuildLayout.ExplicitAsset asset in BuildLayoutHelpers.EnumerateAssets(bundle))
{
@@ -55,10 +57,15 @@ public BuildLayout.ExplicitAsset GetAsset(int bundleCode, int assetCode)
private Dictionary m_BuildLayouts = new Dictionary();
private readonly List m_ActiveLayouts = new List();
- public void LoadReports()
+ internal void ClearReports()
{
m_BuildLayouts.Clear();
m_ActiveLayouts.Clear();
+ }
+
+ public void LoadReports()
+ {
+ ClearReports();
if (Directory.Exists(Addressables.BuildReportPath))
{
@@ -95,6 +102,22 @@ public bool LoadManualReport(string path)
return true;
}
+ internal void AddActiveLayout(string buildResultHash)
+ {
+ if (m_BuildLayouts.TryGetValue(Hash128.Parse(buildResultHash), out BuildLayout layout))
+ {
+ AddActiveLayout(layout);
+ return;
+ }
+ throw new Exception($"Unable to add active layout. {buildResultHash} does not exist in loaded reports.");
+ }
+
+ internal void AddActiveLayout(BuildLayout layout)
+ {
+ m_ActiveLayouts.Add(new ActiveLayout(layout));
+
+ }
+
private bool TryLoadLayoutAtPath(string path, out BuildLayout layoutOut, bool logErrors = false)
{
layoutOut = BuildLayout.Open(path);
@@ -114,13 +137,13 @@ private bool TryLoadLayoutAtPath(string path, out BuildLayout layoutOut, bool lo
return true;
}
- public HashSet SetActiveReportsAndGetMissingBuildHashes(NativeArray loadedRuntimeCatalogs)
+ public HashSet SetActiveReportsAndGetMissingBuildHashes(IEnumerable loadedRuntimeCatalogs)
{
HashSet oldActives = new HashSet(m_ActiveLayouts);
HashSet missingBuildHashes = new HashSet();
- for (int i = 0; i < loadedRuntimeCatalogs.Length; ++i)
+ foreach(CatalogFrameData loadedRuntimeCatalog in loadedRuntimeCatalogs)
{
- var recordedHash = loadedRuntimeCatalogs[i].BuildResultHash;
+ var recordedHash = loadedRuntimeCatalog.BuildResultHash;
var layout = m_ActiveLayouts.Find(activeLayout => activeLayout.BuildResultHash == recordedHash);
if (layout != null)
{
@@ -129,7 +152,9 @@ public HashSet SetActiveReportsAndGetMissingBuildHashes(NativeArray GetFrameMetaData(FrameDataViewRef rawFrameDataViewRef, Guid id, int tag) where T : struct
+ {
+ return rawFrameDataViewRef.frameDataView.GetFrameMetaData(id, tag);
+ }
+ }
+}
diff --git a/Editor/Diagnostics/Profiler/EditorFrameDataStore.cs.meta b/Editor/Diagnostics/Profiler/EditorFrameDataStore.cs.meta
new file mode 100644
index 00000000..46963fc0
--- /dev/null
+++ b/Editor/Diagnostics/Profiler/EditorFrameDataStore.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 95db4c4b9616444abce778abd4ab9e2a
+timeCreated: 1712949974
\ No newline at end of file
diff --git a/Editor/Diagnostics/Profiler/FrameDataViewRef.cs b/Editor/Diagnostics/Profiler/FrameDataViewRef.cs
new file mode 100644
index 00000000..40deeefb
--- /dev/null
+++ b/Editor/Diagnostics/Profiler/FrameDataViewRef.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEditor.Profiling;
+
+namespace UnityEditor.AddressableAssets.Diagnostics
+{
+ // this is a wrapper to make it possible to pass around context for testing
+ internal class FrameDataViewRef : IDisposable
+ {
+ public int frameIndex { get; set; }
+ public int threadIndex { get; set; }
+ public FrameDataView frameDataView { get; set; }
+
+ public bool valid { get; set; }
+
+ public FrameDataViewRef()
+ {
+ }
+
+ public void Dispose()
+ {
+ frameDataView?.Dispose();
+ }
+ }
+}
diff --git a/Editor/Diagnostics/Profiler/FrameDataViewRef.cs.meta b/Editor/Diagnostics/Profiler/FrameDataViewRef.cs.meta
new file mode 100644
index 00000000..24a5ddd2
--- /dev/null
+++ b/Editor/Diagnostics/Profiler/FrameDataViewRef.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8046608232ba43ce8d11c6e20c248267
+timeCreated: 1712953993
\ No newline at end of file
diff --git a/Editor/Diagnostics/Profiler/IFrameDataStore.cs b/Editor/Diagnostics/Profiler/IFrameDataStore.cs
new file mode 100644
index 00000000..6d25c1a9
--- /dev/null
+++ b/Editor/Diagnostics/Profiler/IFrameDataStore.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using Unity.Collections;
+using UnityEditor.Profiling;
+
+namespace UnityEditor.AddressableAssets.Diagnostics
+{
+ internal interface IFrameDataStore
+ {
+ public FrameDataViewRef GetRawFrameDataView(int frameIndex, int threadIndex);
+ public IEnumerable GetFrameMetaData(FrameDataViewRef frameDataViewRef, Guid id, int tag) where T : struct;
+ }
+}
diff --git a/Editor/Diagnostics/Profiler/IFrameDataStore.cs.meta b/Editor/Diagnostics/Profiler/IFrameDataStore.cs.meta
new file mode 100644
index 00000000..9c66345c
--- /dev/null
+++ b/Editor/Diagnostics/Profiler/IFrameDataStore.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 303dba846ec041a2907f15fad1de0aff
+timeCreated: 1712949893
\ No newline at end of file
diff --git a/Editor/GUI/AssetInspectorGUI.cs b/Editor/GUI/AssetInspectorGUI.cs
index 99f8c482..be5c4a48 100644
--- a/Editor/GUI/AssetInspectorGUI.cs
+++ b/Editor/GUI/AssetInspectorGUI.cs
@@ -434,7 +434,21 @@ internal static List GatherTargetInfos(Object[] targets, Addressable
if (s_Cache == null && aaSettings != null)
s_Cache = new AddressableAssetSettings.Cache>(aaSettings);
if (s_Cache != null && s_Cache.TryGetCached(selectionHashCode, out targetInfos))
- return targetInfos;
+ {
+ bool isValid = true;
+ foreach(var targetInfo in targetInfos)
+ {
+ if (targetInfo.MainAssetEntry?.parentGroup == null)
+ {
+ isValid = false;
+ break;
+ }
+ }
+ if (isValid)
+ return targetInfos;
+ else
+ s_Cache.Remove(selectionHashCode);
+ }
targetInfos = new List(targets.Length);
AddressableAssetEntry entry;
diff --git a/Editor/Settings/AddressableAssetEntry.cs b/Editor/Settings/AddressableAssetEntry.cs
index fc2a9d62..0b927319 100644
--- a/Editor/Settings/AddressableAssetEntry.cs
+++ b/Editor/Settings/AddressableAssetEntry.cs
@@ -547,7 +547,7 @@ internal void GatherFolderEntries(List assets, bool recur
if (entry != null)
{
- entry.m_Labels = m_Labels;
+ entry.m_Labels.UnionWith(m_Labels);
if (entryFilter == null || entryFilter(entry))
assets.Add(entry);
@@ -572,7 +572,7 @@ internal void GatherFolderEntries(List assets, bool recur
var entry = settings.CreateSubEntryIfUnique(AssetDatabase.AssetPathToGUID(folder), address + GetRelativePath(folder, path), this);
if (entry != null)
{
- entry.m_Labels = m_Labels;
+ entry.m_Labels.UnionWith(m_Labels);
entry.IsFolder = true;
if (entryFilter == null || entryFilter(entry))
assets.Add(entry);
@@ -616,7 +616,7 @@ internal AddressableAssetEntry GetFolderSubEntry(string subAssetGuid, string sub
var folderEntry = settings.CreateSubEntryIfUnique(folderGuid, address + "/" + folderPath.Remove(assetPath.Length), this);
if (folderEntry != null)
{
- folderEntry.m_Labels = m_Labels;
+ folderEntry.m_Labels.UnionWith(m_Labels);
folderEntry.IsFolder = true;
}
else
@@ -627,7 +627,7 @@ internal AddressableAssetEntry GetFolderSubEntry(string subAssetGuid, string sub
if (assetEntry != null)
{
- assetEntry.m_Labels = m_Labels;
+ assetEntry.m_Labels.UnionWith(m_Labels);
assetEntry.IsFolder = false;
}
diff --git a/Editor/Settings/AddressableAssetSettings.cs b/Editor/Settings/AddressableAssetSettings.cs
index 6642618f..3d08262b 100644
--- a/Editor/Settings/AddressableAssetSettings.cs
+++ b/Editor/Settings/AddressableAssetSettings.cs
@@ -61,6 +61,13 @@ public void Add(T1 key, T2 value)
m_TargetInfoCache.Add(key, value);
}
+ public void Remove(T1 key)
+ {
+ if (!IsValid())
+ m_CurrentCacheVersion = m_Settings.currentHash;
+ m_TargetInfoCache.Remove(key);
+ }
+
private bool IsValid()
{
if (m_TargetInfoCache.Count > 0)
@@ -1186,8 +1193,7 @@ public Hash128 currentHash
internal void DataBuilderCompleted(IDataBuilder builder, IDataBuilderResult result)
{
- if (OnDataBuilderComplete != null)
- OnDataBuilderComplete(this, builder, result);
+ OnDataBuilderComplete?.Invoke(this, builder, result);
}
///
@@ -2173,10 +2179,8 @@ public void SetDirty(ModificationEvent modificationEvent, object eventData, bool
{
if (postEvent)
{
- if (OnModificationGlobal != null)
- OnModificationGlobal(this, modificationEvent, eventData);
- if (OnModification != null)
- OnModification(this, modificationEvent, eventData);
+ OnModificationGlobal?.Invoke(this, modificationEvent, eventData);
+ OnModification?.Invoke(this, modificationEvent, eventData);
}
if (settingsModified && IsPersisted)
@@ -2254,7 +2258,12 @@ public AddressableAssetEntry FindAssetEntry(string guid, bool includeImplicit)
if (m_FindAssetEntryCache != null)
{
if (m_FindAssetEntryCache.TryGetCached(guid, out foundEntry))
- return foundEntry;
+ {
+ if (foundEntry?.parentGroup == null)
+ m_FindAssetEntryCache.Remove(guid);
+ else
+ return foundEntry;
+ }
}
else
m_FindAssetEntryCache = new Cache(this);
@@ -3036,8 +3045,7 @@ internal AddressablesPlayerBuildResult BuildPlayerContentImpl(AddressablesDataBu
else
Debug.Log($"Addressable content successfully built (duration : {TimeSpan.FromSeconds(result.Duration).ToString("g")})");
- if (BuildScript.buildCompleted != null)
- BuildScript.buildCompleted(result);
+ BuildScript.buildCompleted?.Invoke(result);
AssetDatabase.Refresh();
return result;
}
@@ -3264,7 +3272,7 @@ public void OnBeforeSerialize()
{
// m_InitializationObjects, m_DataBuilders, and m_GroupTemplateObjects are serialized by array index
profileSettings.profiles.Sort((a, b) => string.CompareOrdinal(a.id, b.id));
- m_GroupAssets.Sort((a, b) => string.CompareOrdinal(a.Guid, b.Guid));
+ m_GroupAssets.Sort((a, b) => string.CompareOrdinal(a?.Guid, b?.Guid));
}
///
diff --git a/Runtime/Addressables.cs b/Runtime/Addressables.cs
index d779f817..134c48ba 100644
--- a/Runtime/Addressables.cs
+++ b/Runtime/Addressables.cs
@@ -568,6 +568,18 @@ static AddressablesImpl m_Addressables
}
}
+ ///
+ /// Returns the Addressables package version in Unity 2019.3 or newer
+ ///
+ public static string Version
+ {
+#if (UNITY_EDITOR)
+ get => UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(Addressables).Assembly).version;
+#else
+ get => "";
+#endif
+ }
+
///
/// Stores the ResourceManager associated with this Addressables instance.
///
@@ -591,7 +603,16 @@ static void RegisterPlayModeStateChange()
static void SetAddressablesReInitFlagOnExitPlayMode(PlayModeStateChange change)
{
if (change == PlayModeStateChange.EnteredEditMode || change == PlayModeStateChange.ExitingPlayMode)
- reinitializeAddressables = true;
+ {
+ EditorApplication.delayCall -= EnableReinitializeAddressablesFlag;
+ EditorApplication.delayCall += EnableReinitializeAddressablesFlag;
+ }
+ }
+
+ static void EnableReinitializeAddressablesFlag()
+ {
+ reinitializeAddressables = true;
+ EditorApplication.delayCall -= EnableReinitializeAddressablesFlag;
}
#endif
@@ -1441,7 +1462,7 @@ public static void Release(TObject obj)
/// The operation handle to release.
public static void Release(AsyncOperationHandle handle)
{
- m_Addressables.Release(handle);
+ handle.Release();
}
///
@@ -1450,7 +1471,7 @@ public static void Release(AsyncOperationHandle handle)
/// The operation handle to release.
public static void Release(AsyncOperationHandle handle)
{
- m_Addressables.Release(handle);
+ handle.Release();
}
///
@@ -1470,7 +1491,7 @@ public static bool ReleaseInstance(GameObject instance)
/// Returns true if the instance was successfully released.
public static bool ReleaseInstance(AsyncOperationHandle handle)
{
- m_Addressables.Release(handle);
+ handle.Release();
return true;
}
@@ -1481,7 +1502,7 @@ public static bool ReleaseInstance(AsyncOperationHandle handle)
/// Returns true if the instance was successfully released.
public static bool ReleaseInstance(AsyncOperationHandle handle)
{
- m_Addressables.Release(handle);
+ handle.Release();
return true;
}
diff --git a/Runtime/AddressablesImpl.cs b/Runtime/AddressablesImpl.cs
index 74d2786d..9d052e48 100644
--- a/Runtime/AddressablesImpl.cs
+++ b/Runtime/AddressablesImpl.cs
@@ -42,14 +42,7 @@ public IInstanceProvider InstanceProvider
public ISceneProvider SceneProvider;
public ResourceManager ResourceManager
- {
- get
- {
- if (m_ResourceManager == null)
- m_ResourceManager = new ResourceManager(new DefaultAllocationStrategy());
- return m_ResourceManager;
- }
- }
+ { get => m_ResourceManager; }
public int CatalogRequestsTimeout
{
@@ -154,7 +147,7 @@ internal void OnSceneUnloaded(Scene scene)
if (sceneHandle.Result.ReleaseSceneOnSceneUnloaded)
{
var op = SceneProvider.ReleaseScene(m_ResourceManager, sceneHandle);
- AutoReleaseHandleOnCompletion(op);
+ op.ReleaseHandleOnCompletion();
}
break;
}
@@ -367,7 +360,7 @@ public AsyncOperationHandle InitializeAsync(string runtimeData
return m_InitializationOperation;
var completedOperation = ResourceManager.CreateCompletedOperation(m_ResourceLocators[0].Locator, errorMsg: null);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(completedOperation);
+ completedOperation.ReleaseHandleOnCompletion();
return completedOperation;
}
@@ -425,7 +418,7 @@ public AsyncOperationHandle InitializeAsync(string runtimeData
if (!m_InitializationOperation.IsValid())
m_InitializationOperation = Initialization.InitializationOperation.CreateInitializationOperation(this, runtimeDataPath, providerSuffix);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(m_InitializationOperation);
+ m_InitializationOperation.ReleaseHandleOnCompletion();
return m_InitializationOperation;
}
@@ -471,11 +464,13 @@ public AsyncOperationHandle InitializeAsync(bool autoReleaseHa
public ResourceLocationBase CreateCatalogLocationWithHashDependencies(string catalogPath, string hashFilePath) where T : IResourceProvider
{
- var catalogLoc = new ResourceLocationBase(catalogPath, catalogPath, typeof(T).FullName, typeof(IResourceLocator));
- catalogLoc.Data = new ProviderLoadRequestOptions()
+ var catalogLoc = new ResourceLocationBase(catalogPath, catalogPath, typeof(T).FullName, typeof(IResourceLocator))
{
- IgnoreFailures = false,
- WebRequestTimeout = CatalogRequestsTimeout
+ Data = new ProviderLoadRequestOptions()
+ {
+ IgnoreFailures = false,
+ WebRequestTimeout = CatalogRequestsTimeout
+ }
};
if (!string.IsNullOrEmpty(hashFilePath))
@@ -497,14 +492,18 @@ public AsyncOperationHandle InitializeAsync(bool autoReleaseHa
// The file name of the local cached catalog + hash file is the hash code of the remote hash path, without query parameters (if any).
string cacheHashFilePath = ResolveInternalId(kCacheDataFolder + tmpPath.GetHashCode() + ".hash");
#endif
- var hashResourceLocation = new ResourceLocationBase(hashFilePath, hashFilePath, typeof(TextDataProvider).FullName, typeof(string));
- hashResourceLocation.Data = hashOptions.Copy();
+ var hashResourceLocation = new ResourceLocationBase(hashFilePath, hashFilePath, typeof(TextDataProvider).FullName, typeof(string))
+ {
+ Data = hashOptions.Copy()
+ };
catalogLoc.Dependencies.Add(hashResourceLocation);
- var cacheResourceLocation = new ResourceLocationBase(cacheHashFilePath, cacheHashFilePath, typeof(TextDataProvider).FullName, typeof(string));
- cacheResourceLocation.Data = hashOptions.Copy();
+ var cacheResourceLocation = new ResourceLocationBase(cacheHashFilePath, cacheHashFilePath, typeof(TextDataProvider).FullName, typeof(string))
+ {
+ Data = hashOptions.Copy()
+ };
catalogLoc.Dependencies.Add(cacheResourceLocation);
- //If you're explicitly loading a contnet catalog, we'll just set the "local" filepath to be the same as the "cached" one
+ //If you're explicitly loading a content catalog, we'll just set the "local" filepath to be the same as the "cached" one
catalogLoc.Dependencies.Add(cacheResourceLocation);
}
@@ -527,7 +526,7 @@ public AsyncOperationHandle LoadContentCatalogAsync(string cat
return ResourceManager.CreateChainOperation(ChainOperation, op => LoadContentCatalogAsync(catalogPath, autoReleaseHandle, providerSuffix));
var handle = Initialization.InitializationOperation.LoadContentCatalog(this, catalogLoc, providerSuffix);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
QueueEditorUpdateIfNeeded();
return handle;
}
@@ -779,10 +778,9 @@ void OnSceneHandleCompleted(AsyncOperationHandle handle)
if (handle.Status == AsyncOperationStatus.Succeeded)
{
m_SceneInstances.Add(handle);
- if (!m_resultToHandle.ContainsKey(handle.Result))
+ if (m_resultToHandle.TryAdd(handle.Result, handle))
{
handle.Destroyed += m_OnHandleDestroyedAction;
- m_resultToHandle.Add(handle.Result, handle);
}
}
}
@@ -791,10 +789,9 @@ void OnHandleCompleted(AsyncOperationHandle handle)
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
- if (!m_resultToHandle.ContainsKey(handle.Result))
+ if (m_resultToHandle.TryAdd(handle.Result, handle))
{
handle.Destroyed += m_OnHandleDestroyedAction;
- m_resultToHandle.Add(handle.Result, handle);
}
}
}
@@ -809,7 +806,7 @@ public void Release(TObject obj)
AsyncOperationHandle handle;
if (m_resultToHandle.TryGetValue(obj, out handle))
- Release(handle);
+ handle.Release();
else
{
LogError("Addressables.Release was called on an object that Addressables was not previously aware of. Thus nothing is being released");
@@ -818,21 +815,6 @@ public void Release(TObject obj)
public void Release(AsyncOperationHandle handle)
{
- if (typeof(TObject) == typeof(SceneInstance))
- {
- SceneInstance sceneInstance = (SceneInstance)Convert.ChangeType(handle.Result, typeof(SceneInstance));
- if (sceneInstance.Scene.isLoaded && handle.ReferenceCount == 1)
- {
- if (ActiveSceneInstances == 1 && m_SceneInstances.First().Equals(handle))
- m_SceneInstances.Clear();
- UnloadSceneAsync(handle, UnloadSceneOptions.None, true);
- }
- else if (!sceneInstance.Scene.isLoaded && handle.ReferenceCount == 2 && !handle.UnloadSceneOpExcludeReleaseCallback)
- {
- AutoReleaseHandleOnCompletion(handle);
- }
- }
-
m_ResourceManager.Release(handle);
}
@@ -973,7 +955,7 @@ AsyncOperationHandle DownloadDependenciesAsyncWithChain(AsyncOperationHandle dep
{
var handle = ResourceManager.CreateChainOperation(dep, op => DownloadDependenciesAsync(key).Convert>());
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
@@ -1016,7 +998,7 @@ public AsyncOperationHandle DownloadDependenciesAsync(object key, bool autoRelea
{
var handle = ResourceManager.CreateCompletedOperationWithException>(null, new InvalidKeyException(key, typeof(object), this));
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
else
@@ -1025,7 +1007,7 @@ public AsyncOperationHandle DownloadDependenciesAsync(object key, bool autoRelea
WrapAsDownloadLocations(dlLocations);
var handle = LoadAssetsAsync(dlLocations, null, true);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
}
@@ -1034,7 +1016,7 @@ AsyncOperationHandle DownloadDependenciesAsyncWithChain(AsyncOperationHandle dep
{
var handle = ResourceManager.CreateChainOperation(dep, op => DownloadDependenciesAsync(locations).Convert>());
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
@@ -1048,7 +1030,7 @@ public AsyncOperationHandle DownloadDependenciesAsync(IList l
WrapAsDownloadLocations(dlLocations);
var handle = LoadAssetsAsync(dlLocations, null, true);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
@@ -1056,7 +1038,7 @@ AsyncOperationHandle DownloadDependenciesAsyncWithChain(AsyncOperationHandle dep
{
var handle = ResourceManager.CreateChainOperation(dep, op => DownloadDependenciesAsync(keys, mode).Convert>());
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
@@ -1071,7 +1053,7 @@ public AsyncOperationHandle DownloadDependenciesAsync(IEnumerable keys, Addressa
{
var handle = ResourceManager.CreateCompletedOperationWithException>(null, new InvalidKeyException(keys, typeof(object), mode, this));
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
else
@@ -1080,7 +1062,7 @@ public AsyncOperationHandle DownloadDependenciesAsync(IEnumerable keys, Addressa
WrapAsDownloadLocations(dlLocations);
var handle = LoadAssetsAsync(dlLocations, null, true);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(handle);
+ handle.ReleaseHandleOnCompletion();
return handle;
}
}
@@ -1128,29 +1110,9 @@ internal bool ClearDependencyCacheForKey(object key)
return result;
}
- internal void AutoReleaseHandleOnCompletion(AsyncOperationHandle handle)
- {
- handle.Completed += op => Release(op);
- }
-
- internal void AutoReleaseHandleOnCompletion(AsyncOperationHandle handle)
- {
- handle.Completed += op => Release(op);
- }
-
- internal void AutoReleaseHandleOnCompletion(AsyncOperationHandle handle, bool unloadSceneOpExcludeReleaseCallback)
- {
- handle.Completed += op =>
- {
- if (unloadSceneOpExcludeReleaseCallback)
- op.UnloadSceneOpExcludeReleaseCallback = true;
- Release(op);
- };
- }
-
internal void AutoReleaseHandleOnTypelessCompletion(AsyncOperationHandle handle)
{
- handle.CompletedTypeless += op => Release(op);
+ handle.CompletedTypeless += op => op.Release();
}
public AsyncOperationHandle ClearDependencyCacheAsync(object key, bool autoReleaseHandle)
@@ -1161,7 +1123,7 @@ public AsyncOperationHandle ClearDependencyCacheAsync(object key, bool aut
var chainOp = ResourceManager.CreateChainOperation(ChainOperation,
op => ClearDependencyCacheAsync(key, autoReleaseHandle));
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(chainOp);
+ chainOp.ReleaseHandleOnCompletion();
return chainOp;
}
@@ -1169,7 +1131,7 @@ public AsyncOperationHandle ClearDependencyCacheAsync(object key, bool aut
var completedOp = ResourceManager.CreateCompletedOperation(result, result ? String.Empty : "Unable to clear the cache. AssetBundle's may still be loaded for the given key.");
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(completedOp);
+ completedOp.ReleaseHandleOnCompletion();
return completedOp;
}
@@ -1181,7 +1143,7 @@ public AsyncOperationHandle ClearDependencyCacheAsync(IList ClearDependencyCacheAsync(locations, autoReleaseHandle));
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(chainOp);
+ chainOp.ReleaseHandleOnCompletion();
return chainOp;
}
@@ -1191,7 +1153,7 @@ public AsyncOperationHandle ClearDependencyCacheAsync(IList ClearDependencyCacheAsync(IEnumerable keys, bo
var chainOp = ResourceManager.CreateChainOperation(ChainOperation,
op => ClearDependencyCacheAsync(keys, autoReleaseHandle));
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(chainOp);
+ chainOp.ReleaseHandleOnCompletion();
return chainOp;
}
@@ -1213,7 +1175,7 @@ public AsyncOperationHandle ClearDependencyCacheAsync(IEnumerable keys, bo
var completedOp = ResourceManager.CreateCompletedOperation(result, result ? String.Empty : "Unable to clear the cache. AssetBundle's may still be loaded for the given key(s).");
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(completedOp);
+ completedOp.ReleaseHandleOnCompletion();
return completedOp;
}
@@ -1294,7 +1256,7 @@ public bool ReleaseInstance(GameObject instance)
AsyncOperationHandle handle;
if (m_resultToHandle.TryGetValue(instance, out handle))
- Release(handle);
+ handle.Release();
else
return false;
@@ -1392,7 +1354,7 @@ internal AsyncOperationHandle InternalUnloadScene(AsyncOperationH
QueueEditorUpdateIfNeeded();
var relOp = SceneProvider.ReleaseScene(ResourceManager, handle, unloadOptions);
if (autoReleaseHandle)
- AutoReleaseHandleOnCompletion(relOp, true);
+ relOp.ReleaseHandleOnCompletion();
return relOp;
}
@@ -1409,7 +1371,7 @@ internal AsyncOperationHandle> CheckForCatalogUpdates(bool autoRele
return CheckForCatalogUpdatesWithChain(autoReleaseHandle);
if (m_ActiveCheckUpdateOperation.IsValid())
- Release(m_ActiveCheckUpdateOperation);
+ m_ActiveCheckUpdateOperation.Release();
m_ActiveCheckUpdateOperation = new CheckCatalogsOperation(this).Start(m_ResourceLocators);
if (autoReleaseHandle)
diff --git a/Runtime/AssetReference.cs b/Runtime/AssetReference.cs
index 9df0c89a..fd8b9f10 100644
--- a/Runtime/AssetReference.cs
+++ b/Runtime/AssetReference.cs
@@ -617,7 +617,7 @@ public virtual void ReleaseAsset()
return;
}
- Addressables.Release(m_Operation);
+ m_Operation.Release();
m_Operation = default(AsyncOperationHandle);
}
@@ -842,7 +842,7 @@ public virtual bool SetEditorSubObject(Object value)
{
if (s.name == value.name && s.GetType() == value.GetType())
{
- m_SubObjectGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(value));
+ m_SubObjectGUID = String.Empty;
m_SubObjectName = s.name;
m_SubObjectType = s.GetType().AssemblyQualifiedName;
m_EditorAssetChanged = true;
diff --git a/Runtime/Initialization/CheckCatalogsOperation.cs b/Runtime/Initialization/CheckCatalogsOperation.cs
index 07a1e270..8555b6b9 100644
--- a/Runtime/Initialization/CheckCatalogsOperation.cs
+++ b/Runtime/Initialization/CheckCatalogsOperation.cs
@@ -61,7 +61,7 @@ protected override bool InvokeWaitForCompletion()
protected override void Destroy()
{
- m_Addressables.Release(m_DepOp);
+ m_DepOp.Release();
}
///
diff --git a/Runtime/Initialization/InitializationObjectsOperation.cs b/Runtime/Initialization/InitializationObjectsOperation.cs
index 3e7c0b89..e4d6f83d 100644
--- a/Runtime/Initialization/InitializationObjectsOperation.cs
+++ b/Runtime/Initialization/InitializationObjectsOperation.cs
@@ -115,7 +115,7 @@ protected override void Execute()
{
bool success = obj.Status == AsyncOperationStatus.Succeeded;
Complete(true, success, success ? "" : $"{obj.DebugName}, status={obj.Status}, result={obj.Result} failed initialization.");
- m_Addressables.Release(m_DepOp);
+ m_DepOp.Release();
};
}
else
diff --git a/Runtime/Initialization/InitializationOperation.cs b/Runtime/Initialization/InitializationOperation.cs
index 93ec8a3f..74cfc166 100644
--- a/Runtime/Initialization/InitializationOperation.cs
+++ b/Runtime/Initialization/InitializationOperation.cs
@@ -53,10 +53,12 @@ internal static AsyncOperationHandle CreateInitializationOpera
var runtimeDataLocation = new ResourceLocationBase("RuntimeData", playerSettingsLocation, typeof(JsonAssetProvider).FullName, typeof(ResourceManagerRuntimeData));
- var initOp = new InitializationOperation(aa);
- initOp.m_rtdOp = aa.ResourceManager.ProvideResource(runtimeDataLocation);
- initOp.m_ProviderSuffix = providerSuffix;
- initOp.m_InitGroupOps = new InitalizationObjectsOperation();
+ var initOp = new InitializationOperation(aa)
+ {
+ m_rtdOp = aa.ResourceManager.ProvideResource(runtimeDataLocation),
+ m_ProviderSuffix = providerSuffix,
+ m_InitGroupOps = new InitalizationObjectsOperation()
+ };
initOp.m_InitGroupOps.Init(initOp.m_rtdOp, aa);
var groupOpHandle = aa.ResourceManager.StartOperation(initOp.m_InitGroupOps, initOp.m_rtdOp);
@@ -120,7 +122,7 @@ protected override void Execute()
}
}
- m_Addressables.Release(m_rtdOp);
+ m_rtdOp.Release();
if (rtd.CertificateHandlerType != null)
m_Addressables.ResourceManager.CertificateHandlerInstance = Activator.CreateInstance(rtd.CertificateHandlerType) as CertificateHandler;
@@ -210,14 +212,16 @@ static void LoadProvider(AddressablesImpl addressables, ObjectInitializationData
IResourceLocation remoteHashLocation)
{
var data = op.Result;
- addressables.Release(op);
if (data == null)
{
var opException = op.OperationException != null ? new Exception("Failed to load content catalog.", op.OperationException) : new Exception("Failed to load content catalog.");
+ op.Release();
return addressables.ResourceManager.CreateCompletedOperationWithException(null, opException);
}
else
{
+ op.Release();
+
if (data.ResourceProviderData != null)
foreach (var providerData in data.ResourceProviderData)
LoadProvider(addressables, providerData, providerSuffix);
@@ -239,7 +243,7 @@ static void LoadProvider(AddressablesImpl addressables, ObjectInitializationData
data.location.Dependencies[(int)ContentCatalogProvider.DependencyHashIndex.Remote] = remoteHashLocation;
IResourceLocator locMap = data.CreateCustomLocator(data.location.PrimaryKey, providerSuffix);
- addressables.AddResourceLocator(locMap, data.localHash, data.location);
+ addressables.AddResourceLocator(locMap, data.LocalHash, data.location);
addressables.AddResourceLocator(new DynamicResourceLocator(addressables));
return addressables.ResourceManager.CreateCompletedOperation(locMap, string.Empty);
}
@@ -294,7 +298,7 @@ void LoadOpComplete(AsyncOperationHandle op, IList op, IList
@@ -88,7 +88,7 @@ protected override void Execute()
{
var catData = m_DepOp.Result[i].Result as ContentCatalogData;
locator = catData.CreateCustomLocator(catData.location.PrimaryKey);
- localHash = catData.localHash;
+ localHash = catData.LocalHash;
remoteLocation = catData.location;
}
diff --git a/Runtime/ResourceLocators/ContentCatalogData.cs b/Runtime/ResourceLocators/ContentCatalogData.cs
index d8c2f1e2..3206ddc2 100644
--- a/Runtime/ResourceLocators/ContentCatalogData.cs
+++ b/Runtime/ResourceLocators/ContentCatalogData.cs
@@ -78,8 +78,11 @@ public class ContentCatalogData
//used to check the version of the data in case the format needs to change in the future
const int kVersion = 2;
+ ///
+ /// Stores the local catalog hash
+ ///
[NonSerialized]
- internal string localHash;
+ public string LocalHash;
[NonSerialized]
internal IResourceLocation location;
@@ -90,6 +93,11 @@ public class ContentCatalogData
[SerializeField]
internal string m_BuildResultHash;
+ ///
+ /// Stores the hash for the build result
+ ///
+ public string BuildResultHash { get => m_BuildResultHash; set => m_BuildResultHash = value; }
+
///
/// Stores the id of the data provider.
///
@@ -245,7 +253,7 @@ public object Deserialize(BinaryStorageBuffer.Reader reader, Type t, uint offset
cd.SceneProviderData = reader.ReadObject(h.sceneProvider);
cd.ResourceProviderData = reader.ReadObjectArray(h.initObjectsArray).ToList();
- cd.m_BuildResultHash = reader.ReadString(h.buildResultHash);
+ cd.BuildResultHash = reader.ReadString(h.buildResultHash);
return cd;
}
@@ -276,7 +284,7 @@ public uint Serialize(BinaryStorageBuffer.Writer writer, object val)
instanceProvider = writer.WriteObject(cd.InstanceProviderData, false),
sceneProvider = writer.WriteObject(cd.SceneProviderData, false),
initObjectsArray = writer.WriteObjects(cd.m_ResourceProviderData, false),
- buildResultHash = writer.WriteString(cd.m_BuildResultHash)
+ buildResultHash = writer.WriteString(cd.BuildResultHash)
};
writer.Write(headerOffset, in header);
diff --git a/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs b/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs
index 555cf30d..af6c245c 100644
--- a/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs
+++ b/Runtime/ResourceManager/AsyncOperations/AsyncOperationBase.cs
@@ -214,7 +214,7 @@ protected internal void DecrementReferenceCount()
{
if (m_DestroyedAction != null)
{
- m_DestroyedAction.Invoke(new AsyncOperationHandle(this));
+ m_DestroyedAction.Invoke(Handle);
m_DestroyedAction.Clear();
}
@@ -384,7 +384,7 @@ internal void InvokeCompletionEvent()
{
if (m_CompletedActionT != null)
{
- m_CompletedActionT.Invoke(new AsyncOperationHandle(this));
+ m_CompletedActionT.Invoke(Handle);
m_CompletedActionT.Clear();
}
diff --git a/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs b/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs
index 60f30876..934b3eb0 100644
--- a/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs
+++ b/Runtime/ResourceManager/AsyncOperations/AsyncOperationHandle.cs
@@ -15,20 +15,13 @@ public struct AsyncOperationHandle : IEnumerator, IEquatable m_Version; }
internal string LocationName
{
get { return m_LocationName; }
set { m_LocationName = value; }
}
- bool m_UnloadSceneOpExcludeReleaseCallback;
-
- internal bool UnloadSceneOpExcludeReleaseCallback
- {
- get { return m_UnloadSceneOpExcludeReleaseCallback; }
- set { m_UnloadSceneOpExcludeReleaseCallback = value; }
- }
-
///
/// Conversion from typed to non typed handles. This does not increment the reference count.
/// To convert from non-typed back, use AsyncOperationHandle.Convert<T>()
@@ -45,7 +38,6 @@ internal AsyncOperationHandle(AsyncOperationBase op)
m_InternalOp = op;
m_Version = op?.Version ?? 0;
m_LocationName = null;
- m_UnloadSceneOpExcludeReleaseCallback = false;
}
///
@@ -69,7 +61,6 @@ internal AsyncOperationHandle(IAsyncOperation op)
m_InternalOp = (AsyncOperationBase)op;
m_Version = op?.Version ?? 0;
m_LocationName = null;
- m_UnloadSceneOpExcludeReleaseCallback = false;
}
internal AsyncOperationHandle(IAsyncOperation op, int version)
@@ -77,7 +68,6 @@ internal AsyncOperationHandle(IAsyncOperation op, int version)
m_InternalOp = (AsyncOperationBase)op;
m_Version = version;
m_LocationName = null;
- m_UnloadSceneOpExcludeReleaseCallback = false;
}
internal AsyncOperationHandle(IAsyncOperation op, string locationName)
@@ -85,7 +75,6 @@ internal AsyncOperationHandle(IAsyncOperation op, string locationName)
m_InternalOp = (AsyncOperationBase)op;
m_Version = op?.Version ?? 0;
m_LocationName = locationName;
- m_UnloadSceneOpExcludeReleaseCallback = false;
}
internal AsyncOperationHandle(IAsyncOperation op, int version, string locationName)
@@ -93,7 +82,6 @@ internal AsyncOperationHandle(IAsyncOperation op, int version, string locationNa
m_InternalOp = (AsyncOperationBase)op;
m_Version = version;
m_LocationName = locationName;
- m_UnloadSceneOpExcludeReleaseCallback = false;
}
///
@@ -115,6 +103,14 @@ internal AsyncOperationHandle Acquire()
remove { InternalOp.Completed -= value; }
}
+ ///
+ /// Automatically release this handle upon Completed callback
+ ///
+ public void ReleaseHandleOnCompletion()
+ {
+ Completed += op => op.Release();
+ }
+
///
/// Completion event for non-typed callback handlers. If this is assigned on a completed operation, the callback is deferred until the LateUpdate of the current frame.
///
@@ -264,7 +260,7 @@ internal int ReferenceCount
///
/// Release the handle. If the internal operation reference count reaches 0, the resource will be released.
///
- internal void Release()
+ public void Release()
{
InternalOp.DecrementReferenceCount();
m_InternalOp = null;
@@ -337,6 +333,7 @@ public static bool IsWaitingForCompletion
int m_Version;
string m_LocationName;
+ internal int Version{ get => m_Version; }
internal string LocationName
{
get { return m_LocationName; }
@@ -374,7 +371,7 @@ internal AsyncOperationHandle(IAsyncOperation op, int version, string locationNa
///
/// Acquire a new handle to the internal operation. This will increment the reference count, therefore the returned handle must also be released.
///
- /// A new handle to the operation. This handle must also be released.
+ /// A new handle to the operation. This handle must also be released.
internal AsyncOperationHandle Acquire()
{
InternalOp.IncrementReferenceCount();
@@ -390,6 +387,14 @@ internal AsyncOperationHandle Acquire()
remove { InternalOp.CompletedTypeless -= value; }
}
+ ///
+ /// Automatically release this handle upon Completed callback
+ ///
+ public void ReleaseHandleOnCompletion()
+ {
+ Completed += op => op.Release();
+ }
+
///
/// Converts handle to be typed. This does not increment the reference count.
/// To convert back to non-typed, implicit conversion is available.
@@ -527,7 +532,7 @@ internal int ReferenceCount
///
/// Release the handle. If the internal operation reference count reaches 0, the resource will be released.
///
- internal void Release()
+ public void Release()
{
InternalOp.DecrementReferenceCount();
m_InternalOp = null;
diff --git a/Runtime/ResourceManager/AsyncOperations/ProviderOperation.cs b/Runtime/ResourceManager/AsyncOperations/ProviderOperation.cs
index 368754c5..f4cdda0d 100644
--- a/Runtime/ResourceManager/AsyncOperations/ProviderOperation.cs
+++ b/Runtime/ResourceManager/AsyncOperations/ProviderOperation.cs
@@ -26,8 +26,6 @@ internal interface IGenericProviderOperation
internal class ProviderOperation : AsyncOperationBase, IGenericProviderOperation, ICachable
{
private bool m_ReleaseDependenciesOnFailure = true;
- private Action m_CompletionCallback;
- private Action> m_GetDepCallback;
private Func m_GetProgressCallback;
private Func m_GetDownloadProgressCallback;
private Func m_WaitForCompletionCallback;
diff --git a/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs b/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs
new file mode 100644
index 00000000..1c19c47f
--- /dev/null
+++ b/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs
@@ -0,0 +1,24 @@
+using System;
+using UnityEngine.Profiling;
+
+namespace UnityEngine.ResourceManagement.Profiling
+{
+
+ public class EngineEmitter : IProfilerEmitter
+ {
+ public bool IsEnabled
+ {
+ get => Profiler.enabled;
+ }
+
+ public void EmitFrameMetaData(Guid id, int tag, Array data)
+ {
+ Profiler.EmitFrameMetaData(id, tag, data);
+ }
+
+ public void InitialiseCallbacks(Action d)
+ {
+ MonoBehaviourCallbackHooks.Instance.OnLateUpdateDelegate += d;
+ }
+ }
+}
diff --git a/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs.meta b/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs.meta
new file mode 100644
index 00000000..86f3a47b
--- /dev/null
+++ b/Runtime/ResourceManager/Diagnostics/Profiling/EngineEmitter.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 752ec69ac00b4fcbbf48c1967b5a6fa6
+timeCreated: 1712941423
\ No newline at end of file
diff --git a/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs b/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs
new file mode 100644
index 00000000..2cdc10a3
--- /dev/null
+++ b/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace UnityEngine.ResourceManagement.Profiling
+{
+ internal interface IProfilerEmitter
+ {
+ public bool IsEnabled { get; }
+ public void EmitFrameMetaData(Guid id, int tag, Array data);
+
+ public void InitialiseCallbacks(Action onLateUpdateDelegate);
+ }
+}
diff --git a/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs.meta b/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs.meta
new file mode 100644
index 00000000..7ba9a0b1
--- /dev/null
+++ b/Runtime/ResourceManager/Diagnostics/Profiling/IProfilerEmitter.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: fb6d25eccdd3465781dfe97b66e07472
+timeCreated: 1712941313
\ No newline at end of file
diff --git a/Runtime/ResourceManager/Diagnostics/Profiling/ProfilerRuntime.cs b/Runtime/ResourceManager/Diagnostics/Profiling/ProfilerRuntime.cs
index e9662a27..8f2faa57 100644
--- a/Runtime/ResourceManager/Diagnostics/Profiling/ProfilerRuntime.cs
+++ b/Runtime/ResourceManager/Diagnostics/Profiling/ProfilerRuntime.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Unity.Profiling;
-using UnityEngine.Profiling;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
@@ -12,6 +11,7 @@ namespace UnityEngine.ResourceManagement.Profiling
{
internal static class ProfilerRuntime
{
+ internal static IProfilerEmitter m_profilerEmitter = new EngineEmitter();
public static readonly Guid kResourceManagerProfilerGuid = new Guid("4f8a8c93-7634-4ef7-bbbc-6c9928567fa4");
public const int kCatalogTag = 0;
public const int kBundleDataTag = 1;
@@ -39,7 +39,12 @@ public static void Initialise()
AssetLoadCounter.Value = 0;
SceneLoadCounter.Value = 0;
- MonoBehaviourCallbackHooks.Instance.OnLateUpdateDelegate += InstanceOnOnLateUpdateDelegate;
+ m_CatalogData.Data.Clear();
+ m_BundleData.Data.Clear();
+ m_AssetData.Data.Clear();
+ m_SceneData.Data.Clear();
+
+ m_profilerEmitter.InitialiseCallbacks(InstanceOnOnLateUpdateDelegate);
}
private static void InstanceOnOnLateUpdateDelegate(float deltaTime)
@@ -202,15 +207,16 @@ public static void SceneReleased(AsyncOperationHandle handle)
}
}
- private static void PushToProfilerStream()
+ internal static void PushToProfilerStream()
{
- if (!Profiler.enabled)
+ if (!m_profilerEmitter.IsEnabled)
return;
RefreshChangedReferenceCounts();
- Profiler.EmitFrameMetaData(kResourceManagerProfilerGuid, kCatalogTag, m_CatalogData.Values);
- Profiler.EmitFrameMetaData(kResourceManagerProfilerGuid, kBundleDataTag, m_BundleData.Values);
- Profiler.EmitFrameMetaData(kResourceManagerProfilerGuid, kAssetDataTag, m_AssetData.Values);
- Profiler.EmitFrameMetaData(kResourceManagerProfilerGuid, kSceneDataTag, m_SceneData.Values);
+ m_profilerEmitter.EmitFrameMetaData(kResourceManagerProfilerGuid, kCatalogTag, m_CatalogData.Values);
+ m_profilerEmitter.EmitFrameMetaData(kResourceManagerProfilerGuid, kBundleDataTag, m_BundleData.Values);
+ m_profilerEmitter.EmitFrameMetaData(kResourceManagerProfilerGuid, kAssetDataTag, m_AssetData.Values);
+ m_profilerEmitter.EmitFrameMetaData(kResourceManagerProfilerGuid, kSceneDataTag, m_SceneData.Values);
+ m_CatalogData.Data.Clear();
}
private static void RefreshChangedReferenceCounts()
diff --git a/Runtime/ResourceManager/ResourceManager.cs b/Runtime/ResourceManager/ResourceManager.cs
index fe9b6df7..4c8eb530 100644
--- a/Runtime/ResourceManager/ResourceManager.cs
+++ b/Runtime/ResourceManager/ResourceManager.cs
@@ -147,6 +147,9 @@ private struct DeferredCallbackRegisterRequest
internal bool incrementRefCount;
}
+ internal int DeferredCompleteCallbacksCount { get => m_DeferredCompleteCallbacks.Count; }
+ internal int DeferredCallbackCount { get => m_DeferredCallbacksToRegister?.Count ?? 0; }
+
Action m_ReleaseOpNonCached;
Action m_ReleaseOpCached;
Action m_ReleaseInstanceOp;
@@ -597,6 +600,16 @@ public void Release(AsyncOperationHandle handle)
handle.Release();
}
+ ///
+ /// Increment reference count of operation handle.
+ ///
+ /// The handle to the resource to increment the reference count for.
+ /// A new handle to the operation. This handle must also be released.
+ public AsyncOperationHandle Acquire(AsyncOperationHandle handle)
+ {
+ return handle.Acquire();
+ }
+
///
/// Increment reference count of operation handle.
///
diff --git a/Runtime/ResourceManager/ResourceProviders/AssetBundleProvider.cs b/Runtime/ResourceManager/ResourceProviders/AssetBundleProvider.cs
index b5f86920..aa903058 100644
--- a/Runtime/ResourceManager/ResourceProviders/AssetBundleProvider.cs
+++ b/Runtime/ResourceManager/ResourceProviders/AssetBundleProvider.cs
@@ -283,6 +283,8 @@ public enum LoadType
float m_TimeoutTimer = 0;
int m_TimeoutOverFrames = 0;
internal bool m_DownloadOnly = false;
+ int m_LastFrameCount = -1;
+ float m_TimeSecSinceLastUpdate = 0;
internal Func m_RequestRetryCallback = x => x.ShouldRetryDownloadError();
@@ -434,7 +436,7 @@ private void AddBundleToProfiler(Profiling.ContentStatus status, BundleSource so
if (!m_ProvideHandle.IsValid)
return;
- if (status == Profiling.ContentStatus.Active && m_AssetBundle == null)
+ if (status == Profiling.ContentStatus.Active && m_AssetBundle == null) // is this going to suggest load only are released?
Profiling.ProfilerRuntime.BundleReleased(m_Options.BundleName);
else
Profiling.ProfilerRuntime.AddBundleOperation(m_ProvideHandle, m_Options, status, source);
@@ -680,13 +682,25 @@ public void Update(float unscaledDeltaTime)
m_TimeoutTimer = 0;
m_TimeoutOverFrames = 0;
m_LastDownloadedByteCount = operation.webRequest.downloadedBytes;
+
+ m_LastFrameCount = -1;
+ m_TimeSecSinceLastUpdate = 0;
}
else
{
- m_TimeoutTimer += unscaledDeltaTime;
+ float updateTime = unscaledDeltaTime;
+ if (m_LastFrameCount == Time.frameCount)
+ {
+ updateTime = Time.realtimeSinceStartup - m_TimeSecSinceLastUpdate;
+ }
+
+ m_TimeoutTimer += updateTime;
if (HasTimedOut)
operation.webRequest.Abort();
m_TimeoutOverFrames++;
+
+ m_LastFrameCount = Time.frameCount;
+ m_TimeSecSinceLastUpdate = Time.realtimeSinceStartup;
}
}
}
@@ -734,12 +748,12 @@ private void WebRequestOperationCompleted(AsyncOperation op)
{
if (!m_Completed)
{
- AddBundleToProfiler(Profiling.ContentStatus.Active, m_Source);
if (!(m_ProvideHandle.Location is DownloadOnlyLocation))
{
// this loads the bundle into memory which we don't want to do with download only bundles
m_AssetBundle = downloadHandler.assetBundle;
}
+ AddBundleToProfiler(Profiling.ContentStatus.Active, m_Source);
downloadHandler.Dispose();
downloadHandler = null;
m_ProvideHandle.Complete(this, true, null);
diff --git a/Runtime/ResourceManager/ResourceProviders/AtlasSpriteProvider.cs b/Runtime/ResourceManager/ResourceProviders/AtlasSpriteProvider.cs
index 7d6cb8b1..bd43cc1a 100644
--- a/Runtime/ResourceManager/ResourceProviders/AtlasSpriteProvider.cs
+++ b/Runtime/ResourceManager/ResourceProviders/AtlasSpriteProvider.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.Util;
using UnityEngine.U2D;
@@ -26,5 +27,12 @@ public override void Provide(ProvideHandle providerInterface)
var sprite = atlas.GetSprite(spriteKey);
providerInterface.Complete(sprite, sprite != null, sprite != null ? null : new System.Exception($"Sprite failed to load for location {providerInterface.Location.PrimaryKey}."));
}
+
+ ///
+ public override void Release(IResourceLocation location, object obj)
+ {
+ if (obj is Sprite sprite)
+ Object.Destroy(sprite);
+ }
}
}
diff --git a/Runtime/ResourceManager/ResourceProviders/InstanceProvider.cs b/Runtime/ResourceManager/ResourceProviders/InstanceProvider.cs
index 9a747bd6..6257497d 100644
--- a/Runtime/ResourceManager/ResourceProviders/InstanceProvider.cs
+++ b/Runtime/ResourceManager/ResourceProviders/InstanceProvider.cs
@@ -25,6 +25,10 @@ public GameObject ProvideInstance(ResourceManager resourceManager, AsyncOperatio
///
public void ReleaseInstance(ResourceManager resourceManager, GameObject instance)
{
+ // Guard for null - note that Unity overloads equality for GameObject so `default(GameObject) == null` is true so must use explicit `is null` type guard
+ if (instance is null)
+ return;
+
AsyncOperationHandle resource;
if (!m_InstanceObjectToPrefabHandle.TryGetValue(instance, out resource))
{
@@ -32,7 +36,7 @@ public void ReleaseInstance(ResourceManager resourceManager, GameObject instance
}
else
{
- resourceManager.Release(resource);
+ resource.Release();
m_InstanceObjectToPrefabHandle.Remove(instance);
}
diff --git a/Runtime/ResourceManager/ResourceProviders/SceneProvider.cs b/Runtime/ResourceManager/ResourceProviders/SceneProvider.cs
index d2c19bf0..70641ddf 100644
--- a/Runtime/ResourceManager/ResourceProviders/SceneProvider.cs
+++ b/Runtime/ResourceManager/ResourceProviders/SceneProvider.cs
@@ -26,10 +26,12 @@ class SceneOp : AsyncOperationBase, IUpdateReceiver
int m_Priority;
private AsyncOperationHandle> m_DepOp;
ResourceManager m_ResourceManager;
+ ISceneProvider2 m_provider;
- public SceneOp(ResourceManager rm)
+ public SceneOp(ResourceManager rm, ISceneProvider2 provider)
{
m_ResourceManager = rm;
+ m_provider = provider;
}
internal override DownloadStatus GetDownloadStatus(HashSet