Inheritance: UnityEngine.MonoBehaviour
        /// <summary>
        /// Check Bundles/[Platform]/xxxx.kk exists?
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static bool IsBundleResourceExist(string url)
        {
            if (KResourceModule.IsEditorLoadAsset)
            {
                var editorPath   = "Assets/" + KEngineDef.ResourcesBuildDir + "/" + url;
                var hasEditorUrl = File.Exists(editorPath);
                if (hasEditorUrl)
                {
                    return(true);
                }
            }

            return(KResourceModule.IsResourceExist(KResourceModule.BundlesPathRelative + url.ToLower() + AppEngine.GetConfig(KEngineDefaultConfigs.AssetBundleExt)));
        }
        private IEnumerator CoLoad(string url)
        {
            if (_loaderMode == LoaderMode.Sync)
            {
                Bytes = KResourceModule.LoadAssetsSync(url);
            }
            else
            {
                string _fullUrl;
                var    getResPathType = KResourceModule.GetResourceFullPath(url, _loaderMode == LoaderMode.Async, out _fullUrl);
                if (getResPathType == KResourceModule.GetResourceFullPathType.Invalid)
                {
                    Log.Error("[HotBytesLoader]Error Path: {0}", url);
                    OnFinish(null);
                    yield break;
                }

                _wwwLoader = KWWWLoader.Load(_fullUrl);
                while (!_wwwLoader.IsCompleted)
                {
                    Progress = _wwwLoader.Progress;
                    yield return(null);
                }

                if (!_wwwLoader.IsSuccess)
                {
                    //if (AssetBundlerLoaderErrorEvent != null)
                    //{
                    //    AssetBundlerLoaderErrorEvent(this);
                    //}
                    Log.Error("[HotBytesLoader]Error Load WWW: {0}", url);
                    OnFinish(null);
                    yield break;
                }
#if UNITY_2018_1_OR_NEWER //TODO 换成WebRequst
                //Bytes = _wwwLoader.Www.downloadHandler.data;
                Bytes = _wwwLoader.Www.bytes;
#else
                Bytes = _wwwLoader.Www.bytes;
#endif
            }

            OnFinish(Bytes);
        }
        protected override void Init(string url, params object[] args)
        {
#if UNITY_5 || UNITY_2017_1_OR_NEWER
            PreLoadManifest();
#endif

            base.Init(url);

            _loaderMode = (LoaderMode)args[0];

            if (NewAssetBundleLoaderEvent != null)
            {
                NewAssetBundleLoaderEvent(url);
            }

            RelativeResourceUrl = url;
            KResourceModule.LogRequest("AssetBundle", RelativeResourceUrl);
            KResourceModule.Instance.StartCoroutine(LoadAssetBundle(url));
        }
Exemple #4
0
        private IEnumerator CoLoad(string url)
        {
            if (_loaderMode == LoaderMode.Sync)
            {
                Bytes = LoadSync(url);
            }
            else
            {
                var getResPathType = KResourceModule.GetResourceFullPath(url, _loaderMode == LoaderMode.Async, out _fullUrl);
                if (getResPathType == KResourceModule.GetResourceFullPathType.Invalid)
                {
                    if (Debug.isDebugBuild)
                    {
                        Log.Error("[HotBytesLoader]Error Path: {0}", url);
                    }
                    OnFinish(null);
                    yield break;
                }

                _wwwLoader = KWWWLoader.Load(_fullUrl);
                while (!_wwwLoader.IsCompleted)
                {
                    Progress = _wwwLoader.Progress;
                    yield return(null);
                }

                if (!_wwwLoader.IsSuccess)
                {
                    //if (AssetBundlerLoaderErrorEvent != null)
                    //{
                    //    AssetBundlerLoaderErrorEvent(this);
                    //}
                    Log.Error("[HotBytesLoader]Error Load WWW: {0}", url);
                    OnFinish(null);
                    yield break;
                }

                Bytes = _wwwLoader.Www.bytes;
            }

            OnFinish(Bytes);
        }
        /// <summary>
        /// Unity5下,使用manifest进行AssetBundle的加载
        /// bool isForce,在热更新后,可能需要强制刷新AssetBundleManifest。
        /// </summary>
        public static void PreLoadManifest(bool isForce = false)
        {
            if (_hasPreloadAssetBundleManifest && isForce == false)
            {
                return;
            }

            _hasPreloadAssetBundleManifest = true;
            //此方法不能加载到manifest文件
            //var manifestPath = string.Format("{0}/{1}/{1}.manifest", KResourceModule.BundlesPathRelative,KResourceModule.BuildPlatformName);
            // _mainAssetBundle = AssetBundle.LoadFromFile(manifestPath);
            // _assetBundleManifest = _mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            var          manifestPath = KResourceModule.BundlesPathRelative + KResourceModule.GetBuildPlatformName();
            KBytesLoader bytesLoader  = KBytesLoader.Load(manifestPath, LoaderMode.Sync);

            Debuger.Assert(bytesLoader != null, $"load manifest byte error path:{manifestPath}");
            _mainAssetBundle = AssetBundle.LoadFromMemory(bytesLoader.Bytes);
            Debuger.Assert(_mainAssetBundle != null, "load manifest ab error");
            _assetBundleManifest = _mainAssetBundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
        }
Exemple #6
0
        private IEnumerator _Init(string path, LoaderMode loaderMode)
        {
            IsLoadAssetBundle = AppEngine.GetConfig("KEngine", "IsLoadAssetBundle").ToInt32() != 0;

            Object getAsset = null;

            if (IsEditorLoadAsset)
            {
#if UNITY_EDITOR
                if (path.EndsWith(".unity"))
                {
                    // scene
                    getAsset = KResourceModule.Instance;
                    Log.LogWarning("Load scene from Build Settings: {0}", path);
                }
                else
                {
                    getAsset = UnityEditor.AssetDatabase.LoadAssetAtPath("Assets/" + KEngineDef.ResourcesBuildDir + "/" + path, typeof(UnityEngine.Object));
                    if (getAsset == null)
                    {
                        Log.Error("Asset is NULL(from {0} Folder): {1}", KEngineDef.ResourcesBuildDir, path);
                    }
                }
#else
                Log.Error("`IsEditorLoadAsset` is Unity Editor only");
#endif
                OnFinish(getAsset);
            }
            else if (!IsLoadAssetBundle)
            {
                string extension = Path.GetExtension(path);
                path = path.Substring(0, path.Length - extension.Length); // remove extensions

                getAsset = Resources.Load <Object>(path);
                if (getAsset == null)
                {
                    Log.Error("Asset is NULL(from Resources Folder): {0}", path);
                }
                OnFinish(getAsset);
            }
            else
            {
                _bundleLoader = AssetBundleLoader.Load(path, null, loaderMode);

                while (!_bundleLoader.IsCompleted)
                {
                    if (IsReadyDisposed) // 中途释放
                    {
                        _bundleLoader.Release();
                        OnFinish(null);
                        yield break;
                    }
                    yield return(null);
                }

                if (!_bundleLoader.IsSuccess)
                {
                    Log.Error("[AssetFileLoader]Load BundleLoader Failed(Error) when Finished: {0}", path);
                    _bundleLoader.Release();
                    OnFinish(null);
                    yield break;
                }

                var assetBundle = _bundleLoader.Bundle;

                DateTime beginTime = DateTime.Now;
#if UNITY_5 || UNITY_2017_1_OR_NEWER
                // Unity 5 下,不能用mainAsset, 要取对象名
                var abAssetName = Path.GetFileNameWithoutExtension(Url).ToLower();
                if (!assetBundle.isStreamedSceneAssetBundle)
                {
                    if (loaderMode == LoaderMode.Sync)
                    {
                        getAsset = assetBundle.LoadAsset(abAssetName);
                        Debuger.Assert(getAsset);
                        _bundleLoader.PushLoadedAsset(getAsset);
                    }
                    else
                    {
                        var request = assetBundle.LoadAssetAsync(abAssetName);
                        while (!request.isDone)
                        {
                            yield return(null);
                        }
                        Debuger.Assert(getAsset = request.asset);
                        _bundleLoader.PushLoadedAsset(getAsset);
                    }
                }
                else
                {
                    // if it's a scene in asset bundle, did nothing
                    // but set a fault Object the result
                    getAsset = KResourceModule.Instance;
                }
#else
                // 经过AddWatch调试,.mainAsset这个getter第一次执行时特别久,要做序列化
                //AssetBundleRequest request = assetBundle.LoadAsync("", typeof(Object));// mainAsset
                //while (!request.isDone)
                //{
                //    yield return null;
                //}
                try
                {
                    Debuger.Assert(getAsset = assetBundle.mainAsset);
                }
                catch
                {
                    Log.Error("[OnAssetBundleLoaded:mainAsset]{0}", path);
                }
#endif

                KResourceModule.LogLoadTime("AssetFileBridge", path, beginTime);

                if (getAsset == null)
                {
                    Log.Error("Asset is NULL: {0}", path);
                }
            }

            if (Application.isEditor)
            {
                if (getAsset != null)
                {
                    KResoourceLoadedAssetDebugger.Create(getAsset.GetType().Name, Url, getAsset as Object);
                }

                // 编辑器环境下,如果遇到GameObject,对Shader进行Fix
                if (getAsset is GameObject)
                {
                    var go = getAsset as GameObject;
                    foreach (var r in go.GetComponentsInChildren <Renderer>(true))
                    {
                        RefreshMaterialsShaders(r);
                    }
                }
            }

            if (getAsset != null)
            {
                // 更名~ 注明来源asset bundle 带有类型
                getAsset.name = String.Format("{0}~{1}", getAsset, Url);
            }
            OnFinish(getAsset);
        }
Exemple #7
0
        /// <summary>
        /// 协和加载Assetbundle,加载完后执行callback
        /// </summary>
        /// <param name="url">资源的url</param>
        /// <param name="callback"></param>
        /// <param name="callbackArgs"></param>
        /// <returns></returns>
        private IEnumerator CoLoad(string url)
        {
#if UNITY_2017_1_OR_NEWER
            //在Unity2017.1.1下,路径中包含两种分隔符(/和\),仅限windows平台
            //比如:C:\Code\KSFramework\Product/Bundles/Windows/ui/login.prefab.k)会报: UriFormatException: Invalid URI: Invalid port number
            //此处对路径处理成Unity标准路径格式:C:/Code/KSFramework/Product/Bundles/Windows/ui/login.prefab.k
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
            url = KTool.FormatToAssetUrl(url);
#endif
#endif
            KResourceModule.LogRequest("WWW", url);
            System.DateTime beginTime = System.DateTime.Now;

            // 潜规则:不用LoadFromCache~它只能用在.assetBundle
            Www           = new WWW(url);
            BeginLoadTime = Time.time;
            WWWLoadingCount++;

            //设置AssetBundle解压缩线程的优先级
            Www.threadPriority = Application.backgroundLoadingPriority; // 取用全局的加载优先速度
            while (!Www.isDone)
            {
                Progress = Www.progress;
                yield return(null);
            }

            yield return(Www);

            WWWLoadingCount--;
            Progress = 1;
            if (IsReadyDisposed)
            {
                Log.Error("[KWWWLoader]Too early release: {0}", url);
                OnFinish(null);
                yield break;
            }
            if (!string.IsNullOrEmpty(Www.error))
            {
                if (Application.platform == RuntimePlatform.Android)
                {
                    // TODO: Android下的错误可能是因为文件不存在!
                }

                string fileProtocol = KResourceModule.GetFileProtocol();
                if (url.StartsWith(fileProtocol))
                {
                    string fileRealPath = url.Replace(fileProtocol, "");
                    Log.Error("File {0} Exist State: {1}", fileRealPath, System.IO.File.Exists(fileRealPath));
                }
                Log.Error("[KWWWLoader:Error]{0} {1}", Www.error, url);

                OnFinish(null);
                yield break;
            }
            else
            {
                KResourceModule.LogLoadTime("WWW", url, beginTime);
                if (WWWFinishCallback != null)
                {
                    WWWFinishCallback(url);
                }

                Desc = string.Format("{0}K", Www.bytes.Length / 1024f);
                OnFinish(Www);
            }

            // 预防WWW加载器永不反初始化, 造成内存泄露~
            if (Application.isEditor)
            {
                while (GetCount <KWWWLoader>() > 0)
                {
                    yield return(null);
                }

                yield return(new WaitForSeconds(5f));

                while (Debug.isDebugBuild && !IsReadyDisposed)
                {
                    Log.Error("[KWWWLoader]Not Disposed Yet! : {0}", this.Url);
                    yield return(null);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Initialize the path of AssetBundles store place ( Maybe in PersitentDataPath or StreamingAssetsPath )
        /// </summary>
        /// <returns></returns>
        static void InitResourcePath()
        {
            GameObject resMgr = GameObject.Find("_ResourceModule_");

            if (resMgr == null)
            {
                resMgr = new GameObject("_ResourceModule_");
                GameObject.DontDestroyOnLoad(resMgr);
            }

            _Instance = resMgr.AddComponent <KResourceModule>();

            string editorProductPath = EditorProductFullPath;

            BundlesPathRelative   = string.Format("{0}/{1}/", BundlesDirName, GetBuildPlatformName());
            DocumentResourcesPath = FileProtocol + DocumentResourcesPathWithoutFileProtocol;

            switch (Application.platform)
            {
            case RuntimePlatform.WindowsEditor:
            case RuntimePlatform.OSXEditor:
            {
                ApplicationPath                = string.Format("{0}{1}", GetFileProtocol(), editorProductPath);
                ProductPathWithProtocol        = GetFileProtocol() + EditorProductFullPath + "/";
                ProductPathWithoutFileProtocol = EditorProductFullPath + "/";
                // Resources folder
            }
            break;

            case RuntimePlatform.WindowsPlayer:
            case RuntimePlatform.OSXPlayer:
            {
                string path = Application.streamingAssetsPath.Replace('\\', '/');        //Application.dataPath.Replace('\\', '/');
                                                                                         //                        path = path.Substring(0, path.LastIndexOf('/') + 1);
                ApplicationPath                = string.Format("{0}{1}", GetFileProtocol(), Application.dataPath);
                ProductPathWithProtocol        = string.Format("{0}{1}/", GetFileProtocol(), path);
                ProductPathWithoutFileProtocol = string.Format("{0}/", path);
                // Resources folder
            }
            break;

            case RuntimePlatform.Android:
            {
                ApplicationPath                = string.Concat("jar:", GetFileProtocol(), Application.dataPath, "!/assets");
                ProductPathWithProtocol        = string.Concat(ApplicationPath, "/");
                ProductPathWithoutFileProtocol = string.Concat(Application.dataPath,
                                                               "!/assets/");
                // 注意,StramingAsset在Android平台中,是在壓縮的apk里,不做文件檢查
                // Resources folder
            }
            break;

            case RuntimePlatform.IPhonePlayer:
            {
                ApplicationPath =
                    System.Uri.EscapeUriString(GetFileProtocol() + Application.streamingAssetsPath);         // MacOSX下,带空格的文件夹,空格字符需要转义成%20

                ProductPathWithProtocol = string.Format("{0}/", ApplicationPath);
                // only iPhone need to Escape the f*****g Url!!! other platform works without it!!! Keng Die!
                ProductPathWithoutFileProtocol = Application.streamingAssetsPath + "/";
                // Resources folder
            }
            break;

            default:
            {
                Debuger.Assert(false);
            }
            break;
            }
        }
Exemple #9
0
        /// <summary>
        /// Initialize the path of AssetBundles store place ( Maybe in PersitentDataPath or StreamingAssetsPath )
        /// </summary>
        /// <returns></returns>
        static void InitResourcePath()
        {
            GameObject resMgr = GameObject.Find("_ResourceModule_");
            if (resMgr == null)
            {
                resMgr = new GameObject("_ResourceModule_");
                GameObject.DontDestroyOnLoad(resMgr);
            }

            _Instance = resMgr.AddComponent<KResourceModule>();

            string editorProductPath = EditorProductFullPath;

            BundlesPathRelative = string.Format("{0}/{1}/", BundlesDirName, GetBuildPlatformName());
            DocumentResourcesPath = FileProtocol + DocumentResourcesPathWithoutFileProtocol;

            switch (Application.platform)
            {
                case RuntimePlatform.WindowsEditor:
                case RuntimePlatform.OSXEditor:
                    {
                        ApplicationPath = string.Format("{0}{1}/", GetFileProtocol(), editorProductPath);
                        BundlesPathWithProtocol = GetFileProtocol() + EditorAssetBundleFullPath + "/" + BuildPlatformName + "/";
                        BundlesPathWithoutFileProtocol = EditorAssetBundleFullPath + "/" + BuildPlatformName + "/";
                        // Resources folder
                    }
                    break;
                case RuntimePlatform.WindowsPlayer:
                case RuntimePlatform.OSXPlayer:
                    {
                        string path = Application.streamingAssetsPath.Replace('\\', '/');//Application.dataPath.Replace('\\', '/');
                                                                                         //                        path = path.Substring(0, path.LastIndexOf('/') + 1);
                        ApplicationPath = string.Format("{0}{1}/", GetFileProtocol(), Application.dataPath);
                        BundlesPathWithProtocol = string.Format("{0}{1}/{2}/{3}/", GetFileProtocol(), path, BundlesDirName,
                            GetBuildPlatformName());
                        BundlesPathWithoutFileProtocol = string.Format("{0}/{1}/{2}/", path, BundlesDirName,
                            GetBuildPlatformName());
                        // Resources folder
                    }
                    break;
                case RuntimePlatform.Android:
                    {
                        ApplicationPath = string.Concat("jar:", GetFileProtocol(), Application.dataPath,
                            string.Format("!/assets/{0}/", BundlesDirName));
                        BundlesPathWithProtocol = string.Concat(ApplicationPath, GetBuildPlatformName(), "/");
                        BundlesPathWithoutFileProtocol = string.Concat(Application.dataPath,
                            "!/assets/" + BundlesDirName + "/", GetBuildPlatformName() + "/");
                        // 注意,StramingAsset在Android平台中,是在壓縮的apk里,不做文件檢查
                        // Resources folder
                    }
                    break;
                case RuntimePlatform.IPhonePlayer:
                    {
                        ApplicationPath =
                            System.Uri.EscapeUriString(GetFileProtocol() + Application.streamingAssetsPath + "/" +
                                                       BundlesDirName + "/"); // MacOSX下,带空格的文件夹,空格字符需要转义成%20
                        BundlesPathWithProtocol = string.Format("{0}{1}/", ApplicationPath, GetBuildPlatformName());
                        // only iPhone need to Escape the f*****g Url!!! other platform works without it!!! Keng Die!
                        BundlesPathWithoutFileProtocol = Application.streamingAssetsPath + "/" + BundlesDirName + "/" +
                                                                   GetBuildPlatformName() + "/";
                        // Resources folder
                    }
                    break;
                default:
                    {
                        Debuger.Assert(false);
                    }
                    break;
            }
        }
        private IEnumerator LoadAssetBundle(string relativeUrl)
        {
#if UNITY_5 || UNITY_2017_1_OR_NEWER
            // Unity 5 Manifest中管理了依赖
            var abPath = relativeUrl.ToLower();
            var deps   = _assetBundleManifest.GetAllDependencies(abPath);
            _depLoaders = new AssetBundleLoader[deps.Length];
            for (var d = 0; d < deps.Length; d++)
            {
                var dep = deps[d];
                _depLoaders[d] = AssetBundleLoader.Load(dep, null, _loaderMode);
                if (_depLoaders[d].dependFrom == string.Empty)
                {
                    _depLoaders[d].dependFrom = relativeUrl;
                }
            }
            for (var l = 0; l < _depLoaders.Length; l++)
            {
                var loader = _depLoaders[l];
                while (!loader.IsCompleted)
                {
                    yield return(null);
                }
            }
#endif

#if UNITY_5 || UNITY_2017_1_OR_NEWER
            // Unity 5 AssetBundle自动转小写
            relativeUrl = relativeUrl.ToLower();
#endif
            if (AppConfig.IsLogAbLoadCost)
            {
                beginTime = Time.realtimeSinceStartup;
            }

            string _fullUrl = KResourceModule.GetAbFullPath(relativeUrl);

            if (string.IsNullOrEmpty(_fullUrl))
            {
                OnFinish(null);
                yield break;
            }

            AssetBundle assetBundle = null;
            if (_loaderMode == LoaderMode.Sync)
            {
                assetBundle = AssetBundle.LoadFromFile(_fullUrl);
            }
            else
            {
                var request = AssetBundle.LoadFromFileAsync(_fullUrl);
                while (!request.isDone)
                {
                    if (IsReadyDisposed) // 中途释放
                    {
                        OnFinish(null);
                        yield break;
                    }
                    Progress = request.progress;
                    yield return(null);
                }
                assetBundle = request.assetBundle;
            }
            if (assetBundle == null)
            {
                Log.Error("assetBundle is NULL: {0}", RelativeResourceUrl);
            }
            if (AppConfig.IsLogAbLoadCost)
            {
                Log.Info("[Finish] Load AssetBundle {0}, CostTime {1}s {2}", relativeUrl, Time.realtimeSinceStartup - beginTime, dependFrom);
            }
            if (AppConfig.IsSaveCostToFile && !relativeUrl.StartsWith("ui/"))
            {
                LogFileManager.WriteLoadAbLog(relativeUrl, Time.realtimeSinceStartup - beginTime);
            }
            OnFinish(assetBundle);
        }
Exemple #11
0
        /// <summary>
        /// 协和加载Assetbundle,加载完后执行callback
        /// </summary>
        /// <param name="url">资源的url</param>
        /// <param name="callback"></param>
        /// <param name="callbackArgs"></param>
        /// <returns></returns>
        private IEnumerator CoLoad(string url)
        {
            KResourceModule.LogRequest("WWW", url);
            System.DateTime beginTime = System.DateTime.Now;

            // 潜规则:不用LoadFromCache~它只能用在.assetBundle
            Www           = new WWW(url);
            BeginLoadTime = Time.time;
            WWWLoadingCount++;

            //设置AssetBundle解压缩线程的优先级
            Www.threadPriority = Application.backgroundLoadingPriority; // 取用全局的加载优先速度
            while (!Www.isDone)
            {
                Progress = Www.progress;
                yield return(null);
            }

            yield return(Www);

            WWWLoadingCount--;
            Progress = 1;
            if (IsReadyDisposed)
            {
                Log.Error("[KWWWLoader]Too early release: {0}", url);
                OnFinish(null);
                yield break;
            }
            if (!string.IsNullOrEmpty(Www.error))
            {
                if (Application.platform == RuntimePlatform.Android)
                {
                    // TODO: Android下的错误可能是因为文件不存在!
                }

                string fileProtocol = KResourceModule.GetFileProtocol();
                if (url.StartsWith(fileProtocol))
                {
                    string fileRealPath = url.Replace(fileProtocol, "");
                    Log.Error("File {0} Exist State: {1}", fileRealPath, System.IO.File.Exists(fileRealPath));
                }
                Log.Error("[KWWWLoader:Error]{0} {1}", Www.error, url);

                OnFinish(null);
                yield break;
            }
            else
            {
                KResourceModule.LogLoadTime("WWW", url, beginTime);
                if (WWWFinishCallback != null)
                {
                    WWWFinishCallback(url);
                }

                Desc = string.Format("{0}K", Www.bytes.Length / 1024f);
                OnFinish(Www);
            }

            // 预防WWW加载器永不反初始化, 造成内存泄露~
            if (Application.isEditor)
            {
                while (GetCount <KWWWLoader>() > 0)
                {
                    yield return(null);
                }

                yield return(new WaitForSeconds(5f));

                while (Debug.isDebugBuild && !IsReadyDisposed)
                {
                    Log.Error("[KWWWLoader]Not Disposed Yet! : {0}", this.Url);
                    yield return(null);
                }
            }
        }
Exemple #12
0
        private IEnumerator _Init(string path, LoaderMode loaderMode)
        {
            IsLoadAssetBundle = KEngine.AppEngine.GetConfig("KEngine", "IsLoadAssetBundle").ToInt32() != 0;

            UnityEngine.Object getAsset = null;
            if (!IsLoadAssetBundle)
            {
                string extension = System.IO.Path.GetExtension(path);
                path = path.Substring(0, path.Length - extension.Length); // remove extensions

                getAsset = Resources.Load <UnityEngine.Object>(path);
                if (getAsset == null)
                {
                    Log.Error("Asset is NULL(from Resources Folder): {0}", path);
                }
                OnFinish(getAsset);
            }
            else
            {
                _bundleLoader = KAssetBundleLoader.Load(path, null, loaderMode);

                while (!_bundleLoader.IsCompleted)
                {
                    if (IsReadyDisposed) // 中途释放
                    {
                        _bundleLoader.Release();
                        OnFinish(null);
                        yield break;
                    }
                    yield return(null);
                }

                if (!_bundleLoader.IsSuccess)
                {
                    Log.Error("[KAssetFileLoader]Load BundleLoader Failed(Error) when Finished: {0}", path);
                    _bundleLoader.Release();
                    OnFinish(null);
                    yield break;
                }

                var assetBundle = _bundleLoader.Bundle;

                System.DateTime beginTime = System.DateTime.Now;
#if UNITY_5
                // Unity 5 下,不能用mainAsset, 要取对象名
                var abAssetName = Path.GetFileNameWithoutExtension(Url).ToLower();
                if (loaderMode == LoaderMode.Sync)
                {
                    getAsset = assetBundle.LoadAsset(abAssetName);
                    Debuger.Assert(getAsset);
                }
                else
                {
                    var request = assetBundle.LoadAssetAsync(abAssetName);
                    while (!request.isDone)
                    {
                        yield return(null);
                    }
                    Debuger.Assert(getAsset = request.asset);
                }
#else
                // 经过AddWatch调试,.mainAsset这个getter第一次执行时特别久,要做序列化
                //AssetBundleRequest request = assetBundle.LoadAsync("", typeof(Object));// mainAsset
                //while (!request.isDone)
                //{
                //    yield return null;
                //}
                try
                {
                    Debuger.Assert(getAsset = assetBundle.mainAsset);
                }
                catch
                {
                    Log.Error("[OnAssetBundleLoaded:mainAsset]{0}", path);
                }
#endif

                KResourceModule.LogLoadTime("AssetFileBridge", path, beginTime);

                if (getAsset == null)
                {
                    Log.Error("Asset is NULL: {0}", path);
                }
            }

            if (Application.isEditor)
            {
                if (getAsset != null)
                {
                    KResoourceLoadedAssetDebugger.Create(getAsset.GetType().Name, Url, getAsset as UnityEngine.Object);
                }
            }

            if (getAsset != null)
            {
                // 更名~ 注明来源asset bundle 带有类型
                getAsset.name = string.Format("{0}~{1}", getAsset, Url);
            }
            OnFinish(getAsset);
        }
        /// <summary>
        /// Unity5下,使用manifest进行AssetBundle的加载
        /// bool isForce,在热更新后,可能需要强制刷新AssetBundleManifest。
        /// </summary>
        public static void PreLoadManifest(bool isForce = false)
        {
            if (_hasPreloadAssetBundleManifest && isForce == false)
            {
                return;
            }

            _hasPreloadAssetBundleManifest = true;
            //此方法不能加载到manifest文件
            //var manifestPath = string.Format("{0}/{1}/{1}.manifest", KResourceModule.BundlesPathRelative,KResourceModule.BuildPlatformName);
            // _mainAssetBundle = AssetBundle.LoadFromFile(manifestPath);
            // _assetBundleManifest = _mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
            KBytesLoader bytesLoader = KBytesLoader.Load(KResourceModule.BundlesPathRelative + KResourceModule.GetBuildPlatformName(), LoaderMode.Sync);

            _mainAssetBundle     = AssetBundle.LoadFromMemory(bytesLoader.Bytes);//KResourceModule.LoadSyncFromStreamingAssets(mainAssetBundlePath));
            _assetBundleManifest = _mainAssetBundle.LoadAsset("AssetBundleManifest") as AssetBundleManifest;

            Debuger.Assert(_mainAssetBundle);
            Debuger.Assert(_assetBundleManifest);
        }