diff --git a/Assets/VersionFlow/Runtime/ABEntity.cs b/Assets/VersionFlow/Runtime/ABEntity.cs index 1a96226..91a14ae 100644 --- a/Assets/VersionFlow/Runtime/ABEntity.cs +++ b/Assets/VersionFlow/Runtime/ABEntity.cs @@ -27,6 +27,7 @@ namespace VersionFlow.Runtime public List Assets { get; private set; } /// 此AB所在Chain internal HashSet m_inChains = new HashSet(); + internal static Dictionary s_AssetToABMapper = new Dictionary(); public ABEntity(Bundle bundle, bool isDownloaded) { @@ -191,6 +192,7 @@ namespace VersionFlow.Runtime if (!m_assetRefCount.ContainsKey(result)) { m_assetRefCount[result] = 1; + s_AssetToABMapper[result] = this; OnAssetLoad?.Invoke(this, result); } else m_assetRefCount[result]++; @@ -221,6 +223,7 @@ namespace VersionFlow.Runtime if (!m_assetRefCount.ContainsKey(result)) { m_assetRefCount[result] = 1; + s_AssetToABMapper[result] = this; OnAssetLoad?.Invoke(this, result); #if UNITY_EDITOR @@ -245,6 +248,8 @@ namespace VersionFlow.Runtime { m_assetRefCount.Remove(asset); OnAssetUnLoad?.Invoke(this, asset); + s_AssetToABMapper.Remove(asset); + if (asset is not GameObject) Resources.UnloadAsset(asset); diff --git a/Assets/VersionFlow/Runtime/BundleManager.cs b/Assets/VersionFlow/Runtime/BundleManager.cs index 0577347..359fb77 100644 --- a/Assets/VersionFlow/Runtime/BundleManager.cs +++ b/Assets/VersionFlow/Runtime/BundleManager.cs @@ -23,14 +23,14 @@ namespace VersionFlow.Runtime /// shader变体收集器 public ShaderVariantCollection SVC { get; private set; } - private readonly HashSet m_loadingChains = new HashSet(); + private readonly Dictionary m_loadingChains = new Dictionary(); private readonly Type m_gameObjectType = typeof(GameObject); /// 可选Bundle组:ABEntity private readonly Dictionary m_optionGroupDownloader = new Dictionary(); public string Version { get; set; } = "N/A"; - internal HashSet GetLoadingChains() => m_loadingChains; + internal IEnumerable GetLoadingChains() => m_loadingChains.Values; internal BundleManager(BundleManifest local, BundleManifest remote) { @@ -90,23 +90,38 @@ namespace VersionFlow.Runtime VersionFlowX.Log($"创建资源清单耗时:{sw.Elapsed.Milliseconds}ms"); } - internal BundleManager() + internal BundleManager() { VersionFlowX.BeginCoroutine(AutoReleaseCoroutine()); } - IEnumerator AutoReleaseCoroutine() - { - while (true) - { - if (VersionFlowX.Setting.AutoReleaseBundle && m_unloadDirty) - { - m_unloadDirty = false; - TryUnLoadBundles(); - } + IEnumerator AutoReleaseCoroutine() + { + while (true) + { + if (VersionFlowX.Setting.AutoReleaseBundle && m_unloadDirty) + { + m_unloadDirty = false; + TryUnLoadBundles(); + } + + yield return null; + } + } - yield return null; - } + internal ABEntity GetEntityByAsset(UnityEngine.Object asset) + { + ABEntity.s_AssetToABMapper.TryGetValue(asset, out var entity); + return entity; + } + + internal LoadingChain GetLoadingChainByAsset(UnityEngine.Object asset) + { + var ab = GetEntityByAsset(asset); + if (ab == null) return null; + + m_loadingChains.TryGetValue(ab, out var chain); + return chain; } internal ABEntity GetEntityByAssetPath(string assetPath) @@ -164,18 +179,10 @@ namespace VersionFlow.Runtime internal LoadingChain GetLoadChain(ABEntity ab, bool shaderOnly) { LoadingChain targetChain = null; - foreach (var chain in m_loadingChains) - { - if (chain.m_topEntity == ab) - { - targetChain = chain; - break; - } - } - if (targetChain == null) - { + if (!m_loadingChains.TryGetValue(ab, out targetChain)) + { targetChain = LoadingChain.Create(ab, shaderOnly); - m_loadingChains.Add(targetChain); + m_loadingChains[ab] = targetChain; } return targetChain; @@ -203,7 +210,7 @@ namespace VersionFlow.Runtime //找到已加载场景的loadchain LoadingChain hasSceneChain = null; - foreach (var chain in m_loadingChains) + foreach (var chain in m_loadingChains.Values) { if (chain.m_currentLoadScenePath != null) { @@ -238,7 +245,7 @@ namespace VersionFlow.Runtime //找到已加载场景的loadchain LoadingChain hasSceneChain = null; - foreach (var chain in m_loadingChains) + foreach (var chain in m_loadingChains.Values) { if (chain.m_currentLoadScenePath != null) { @@ -378,18 +385,19 @@ namespace VersionFlow.Runtime asset = null; } else - { - foreach (var chain in m_loadingChains) - { - chain.UnLoadAsset(asset); - } + { + var ab = GetEntityByAsset(asset); + if (ab != null) + { + ab.UnLoadAsset(asset); + } asset = null; - if (!m_unloadDirty && VersionFlowX.Setting.AutoReleaseBundle) - { - m_unloadDirty = true; - } + if (!m_unloadDirty && VersionFlowX.Setting.AutoReleaseBundle) + { + m_unloadDirty = true; + } } } public void ReleaseAsset(IList assetList) where T : UnityEngine.Object @@ -403,7 +411,7 @@ namespace VersionFlow.Runtime assetList.Clear(); } - HashSet m_needRemoveChains = new HashSet(); + HashSet m_needRemoveChains = new HashSet(); /// /// 检查已加载的Bundle的引用计数为0并且没有任何依赖bundle被加载 /// 然后移除它 @@ -417,13 +425,16 @@ namespace VersionFlow.Runtime m_needRemoveChains.Clear(); - foreach (var chain in m_loadingChains) + foreach (var item in m_loadingChains) { - if (chain.TryDispose()) - m_needRemoveChains.Add(chain); - } + var topAB = item.Key; + var chain = item.Value; - m_loadingChains.ExceptWith(m_needRemoveChains); + if (chain.TryDispose()) + m_needRemoveChains.Add(topAB); + } + foreach (var removeChainKey in m_needRemoveChains) + m_loadingChains.Remove(removeChainKey); } /// diff --git a/Assets/VersionFlow/Runtime/LoadingChain/LoadingChain.cs b/Assets/VersionFlow/Runtime/LoadingChain/LoadingChain.cs index 79825ba..c42254a 100644 --- a/Assets/VersionFlow/Runtime/LoadingChain/LoadingChain.cs +++ b/Assets/VersionFlow/Runtime/LoadingChain/LoadingChain.cs @@ -50,8 +50,31 @@ namespace VersionFlow.Runtime } } - void Entity_OnAssetLoad(ABEntity sender, Object asset) => m_loadedAssets[asset] = sender; - void Entity_OnAssetUnLoad(ABEntity sender, Object asset) => m_loadedAssets.Remove(asset); + void Entity_OnAssetLoad(ABEntity sender, Object asset) + { + m_loadedAssets[asset] = sender; + } + void Entity_OnAssetUnLoad(ABEntity sender, Object asset) + { + m_loadedAssets.Remove(asset); + + if (asset is GameObject prefabSrc) + { + m_prefabSrcToInstance.Remove(prefabSrc); + + string needRemoveKey = null; + foreach (var item in prefabSrcCache) + { + if (item.Value == prefabSrc) + { + needRemoveKey = item.Key; + break; + } + } + if (needRemoveKey != null) + prefabSrcCache.Remove(needRemoveKey); + } + } internal ABEntity GetEntityByAssetPath(string assetPath) { @@ -85,14 +108,20 @@ namespace VersionFlow.Runtime return null; } - internal void LoadAllBundle() - { - foreach (var entity in m_entities) entity.LoadAB(); - } + Dictionary prefabSrcCache = new Dictionary(); + internal GameObject Instantiate(string assetPath, Transform parent = null) - { - var prefabSrc = LoadAsset(assetPath); + { + if (assetPath.Contains("audiosourceclone")) + { + UnityEngine.Debug.Log("[123]"); + } + if (!prefabSrcCache.TryGetValue(assetPath, out GameObject prefabSrc)) + { + prefabSrc = LoadAsset(assetPath); + prefabSrcCache[assetPath] = prefabSrc; + } if (prefabSrc == null) return null; @@ -110,12 +139,15 @@ namespace VersionFlow.Runtime } internal IEnumerator InstantiateAsync(string assetPath) - { - var itor = LoadAssetAsync(assetPath); - - while (itor.MoveNext()) yield return itor.Current; - - var prefabSrc = itor.Current as GameObject; + { + if (!prefabSrcCache.TryGetValue(assetPath, out GameObject prefabSrc)) + { + var itor = LoadAssetAsync(assetPath); + while (itor.MoveNext()) yield return itor.Current; + prefabSrc = itor.Current as GameObject; + if (prefabSrc != null) + prefabSrcCache[assetPath] = prefabSrc; + } if (prefabSrc == null) yield break; @@ -220,11 +252,6 @@ namespace VersionFlow.Runtime } } - internal void UnLoadAsset(Object asset) - { - if (m_loadedAssets.TryGetValue(asset, out var ab) && ab != null) ab.UnLoadAsset(asset); - } - internal bool HasEntity(ABEntity ab) => m_entities.Contains(ab); internal bool TryDispose() @@ -233,8 +260,11 @@ namespace VersionFlow.Runtime var hasPrefabInstance = CheckPrefabInstanceRef(out var needRemovePrefabSrcList); - foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset - UnLoadAsset(loadedPrefab); + foreach (var loadedPrefab in needRemovePrefabSrcList) //检测到可以Unload的Asset + { + var ab = VersionFlowX.BundleMgr.GetEntityByAsset(loadedPrefab); + ab.UnLoadAsset(loadedPrefab); + } if (hasPrefabInstance) return false;