public void Update()
        {
            for (int i = m_LoadingAssetBundles.Count - 1; i >= 0; --i)
            {
                IAssetBundle assetBundle = m_LoadingAssetBundles[i];

                if (!m_CreatedAssetBundles.ContainsKey(assetBundle.Name)) // unloaded
                {
                    m_LoadingAssetBundles.RemoveAt(i);
                }
                else if (assetBundle.UpdateLoadingState())
                {
                    LogMessage("AssetBundle: ", assetBundle.Name, " is loaded.");
                    m_LoadingAssetBundles.RemoveAt(i);
                }
            }

            for (int i = m_LoadingAssets.Count - 1; i >= 0; --i)
            {
                AsyncAsset asset = m_LoadingAssets[i];

                if (!m_CreatedAssets.ContainsKey(asset.AssetName)) // unloaded
                {
                    m_LoadingAssets.RemoveAt(i);
                }
                else if (asset.UpdateLoadingState())
                {
                    LogMessage("Asset: ", asset.AssetName, " is loaded.");
                    m_LoadingAssets.RemoveAt(i);
                }
            }
        }
        public AsyncAsset[] LoadAllAssets(string assetBundleName)
        {
            IAssetBundle assetBundle = LoadAssetBundle(assetBundleName);

            string[]     assetNames = m_Catalog.AssetBundles[assetBundleName].Assets;
            AsyncAsset[] assets     = new AsyncAsset[assetNames.Length];

            for (int i = 0; i < assetNames.Length; i++)
            {
                string assetName = assetNames[i];

                if (m_CreatedAssets.TryGetValue(assetName, out AsyncAsset asset))
                {
                    LogMessage("Load Asset: '", assetName, "' from cache.");
                }
                else
                {
                    asset = CreateAssetFromAssetBundle(assetName, typeof(Object), assetBundle);
                }

                assets[i] = asset;
            }

            return(assets);
        }
        public AsyncAsset[] LoadAssets(Type type, params AssetPtr[] ptrs)
        {
            AsyncAsset[] results = new AsyncAsset[ptrs.Length];

            for (int i = 0; i < results.Length; i++)
            {
                results[i] = LoadAsset(ptrs[i], type);
            }

            return(results);
        }
        public AsyncAsset[] LoadAssets(Type type, params string[] names)
        {
            AsyncAsset[] results = new AsyncAsset[names.Length];

            for (int i = 0; i < results.Length; i++)
            {
                results[i] = LoadAsset(names[i], type);
            }

            return(results);
        }
        private AsyncAsset CreateAssetFromAssetBundle(string name, Type type, IAssetBundle assetBundle)
        {
            AsyncAsset asset = new AsyncAsset();

            asset.Initialize(name, type, assetBundle);
            assetBundle.IncreaseRef();

            m_CreatedAssets.Add(name, asset);
            m_LoadingAssets.Add(asset);

            LogMessage("Create Asset: '", name, "'.");
            return(asset);
        }
        public void UnloadAsset(AsyncAsset asset)
        {
            if (!m_CreatedAssets.Remove(asset.AssetName))
            {
                Debug.LogWarning($"Asset '{asset.AssetName}' is not loaded, you can not unload it.");
                return;
            }

            asset.Unload();
            asset.AssetBundle.DecreaseRef();
            LogMessage("Unload Asset: ", asset.AssetName);

            // TODO: 延时卸载 AssetBundle
            if (asset.AssetBundle.RefCount == 0)
            {
                UnloadAssetBundle(asset.AssetBundle);
            }
        }