using TinaX.VFSKit; using UnityEngine; using System.Collections.Generic; using TinaX.VFSKit.Loader; using Cysharp.Threading.Tasks; using System; using TinaX.VFSKit.Exceptions; namespace TinaX.VFSKitInternal { /// /// AssetBundle 内部类 /// public class VFSBundle : IBundle, IDisposable { /// /// 存放的是直接依赖,如果有需要请递归 /// public List Dependencies { get; set; } = new List(); /// /// 这里是直接依赖,如果有需要请递归 /// public string[] DependenciesNames { get; set; } = new string[0]; public AssetBundle AssetBundle { get; private set; } public AssetLoadState LoadState { get; internal set; } = AssetLoadState.Idle; public string AssetBundleName { get; set; } // Path: assets/xxx/xxx.xxx public string LoadedPath { get; set; } //file://xxx/xxx or https://xxx/xxx or xxx://xxx/xxx public string VirtualDiskPath { get; set; } public GroupHandleMode GroupHandleMode { get; set; } public int RefCount { get; internal set; } = 0; public AsyncLazy LoadTask { get; internal set; } public List Assets = new List(); public void Release() { this.DoRelease(); } protected void DoRelease(List release_chain = null) { //release 链 if (release_chain == null) release_chain = new List(); if (!release_chain.Contains(this)) release_chain.Add(this); RefCount--; //处理依赖 foreach(var dep in this.Dependencies) { //循环依赖判断 bool _dep_loop = false; if (release_chain.Contains(dep)) _dep_loop = true; if(!_dep_loop) { dep.DoRelease(release_chain); } } if (RefCount <= 0 && LoadState != AssetLoadState.Unloaded) { this.Unload(); } } public void Unload() { if(this.AssetBundle != null) { this.AssetBundle.Unload(true); this.AssetBundle = null; } LoadState = AssetLoadState.Unloaded; //foreach (var item in Dependencies) // item.Release(); Dependencies.Clear(); DependenciesNames = null; this.ABLoader = null; this.LoadTask = UniTask.CompletedTask.ToAsyncLazy(); } /// /// +1s, 苟... /// 不处理依赖 /// public void Retain() { RefCount++; //foreach (var dep in this.Dependencies) // dep.Retain(); } /// /// +1s, 处理依赖项 /// public void RetainWithDependencies() { this.DoRetainWithDependencies(); } protected void DoRetainWithDependencies(List retain_chain = null) { //retain 链 if (retain_chain == null) retain_chain = new List(); if (!retain_chain.Contains(this)) retain_chain.Add(this); RefCount++; //处理依赖 foreach(var dep in this.Dependencies) { bool _dep_loop = false; if (retain_chain.Contains(dep)) _dep_loop = true; if (!_dep_loop) dep.DoRetainWithDependencies(retain_chain); } } public IAssetBundleLoader ABLoader { get; internal set; } internal int DownloadTimeout { get; set; } = 10; //private BundlesManager bundlesManager; /// /// 同步加载 /// internal void Load() { if (this.LoadState == AssetLoadState.Loaded && this.AssetBundle != null) return; if (LoadState == AssetLoadState.Unloaded) throw new VFSException("[TinaX.VFS] Error: Attempt to load an unloaded assetbundle :" + this.AssetBundleName); LoadState = AssetLoadState.Loading; //其实这时候改没啥用 if (LoadedPath.StartsWith("jar:file://", StringComparison.Ordinal)) { this.AssetBundle = this.ABLoader.LoadAssetBundleFromAndroidStreamingAssets(this.LoadedPath, this.AssetBundleName, this.VirtualDiskPath); } else if (LoadedPath.StartsWith("http://", StringComparison.Ordinal) || LoadedPath.StartsWith("https://", StringComparison.Ordinal) || //LoadedPath.StartsWith("file://", StringComparison.Ordinal)|| LoadedPath.StartsWith("ftp://", StringComparison.Ordinal)) { throw new VFSException("[TinaX.VFS] Error: Connot load from network sync"); } else { this.AssetBundle = ABLoader.LoadAssetBundleFromFile(this.LoadedPath, this.AssetBundleName); } LoadState = AssetLoadState.Loaded; } internal async UniTask LoadAsync() { if (LoadState == AssetLoadState.Loaded && this.AssetBundle != null) return; //已加载 if(LoadState == AssetLoadState.Unloaded) throw new VFSException("[TinaX.VFS] Error: Attempt to load an unloaded assetbundle :" + this.AssetBundleName); await DoLoadAsync(); this.LoadState = AssetLoadState.Loaded; this.LoadTask = UniTask.CompletedTask.ToAsyncLazy(); } private async UniTask DoLoadAsync() { LoadState = AssetLoadState.Loading; //正儿八经的开始加载了 if(LoadedPath.StartsWith("jar:file://", StringComparison.Ordinal)) { this.AssetBundle = await this.ABLoader.LoadAssetBundleFromAndroidStreamingAssetsAsync(LoadedPath, AssetBundleName, this.VirtualDiskPath); } else if(LoadedPath.StartsWith("http://", StringComparison.Ordinal) || LoadedPath.StartsWith("https://", StringComparison.Ordinal) || //LoadedPath.StartsWith("file://", StringComparison.Ordinal)|| LoadedPath.StartsWith("ftp://", StringComparison.Ordinal)) { if(this.GroupHandleMode == GroupHandleMode.RemoteOnly) { this.AssetBundle = await this.ABLoader.LoadAssetBundleFromWebAsync(LoadedPath, AssetBundleName, this.DownloadTimeout); } else { await this.ABLoader.DownloadFile(LoadedPath, VirtualDiskPath, DownloadTimeout); this.AssetBundle = await this.ABLoader.LoadAssetBundleFromFileAsync(this.VirtualDiskPath, this.AssetBundleName); } } else { this.AssetBundle = await this.ABLoader.LoadAssetBundleFromFileAsync(LoadedPath, AssetBundleName); } } public void Dispose() { if(this.AssetBundle != null) { this.AssetBundle.Unload(true); this.AssetBundle = null; } this.ABLoader = null; this.LoadTask = UniTask.CompletedTask.ToAsyncLazy(); this.Dependencies = null; this.DependenciesNames = null; } /// /// 当某个asset有此bundle成功load之后,将其注册进来 /// /// internal protected void RegisterAsset(VFSAsset asset) { if (!this.Assets.Contains(asset)) { this.Assets.Add(asset); } } internal protected void UnRegisterAsset(VFSAsset asset) { if (this.Assets.Contains(asset)) { this.Assets.Remove(asset); } } } }