Example #1
0
        static void loadAsync(string[] assetPaths, ResourcesLoadingLocation resourcesLoadingLocation, bool isLoadScene, Func <string, AsyncOperation>[] sceneAsyncRequestFuncs, System.Action <bool, float, string, T[]> asyncAction)
        {
            // 如果意图加载异步,但是场景场景异步请求回调数量和输入的场景资源路径数量不一样时
            // 直接返回错误
            if (isLoadScene && (assetPaths == null || sceneAsyncRequestFuncs == null || assetPaths.Length != sceneAsyncRequestFuncs.Length))
            {
                asyncAction(false, 1, null, null);
                ResourcesManager.NextFrame(() => asyncAction(true, 1, ResourcesManager.KSwordKitName + ": 加载失败!视图加载异步,但是提供的场景异步请求回调数量和输入的场景资源路径数量不一致。\n请检查参数 `assetPaths` 和参数 `scnenAsyncRequestFuncs`。\n如不明白该API含义,请查阅相关文档。", null));
                return;
            }

            int    c         = assetPaths.Length;
            int    cc        = 0;
            string error     = null;
            var    objs      = new T[c];
            var    _progress = 0f;

            for (var i = 0; i < c; i++)
            {
                var index = i;
                loadAsync(assetPaths[i], resourcesLoadingLocation, isLoadScene, isLoadScene? sceneAsyncRequestFuncs[i] : null, (isdone, progress, _error, obj) => {
                    if (isdone)
                    {
                        cc++;
                        objs[index] = obj;
                        if (!string.IsNullOrEmpty(_error))
                        {
                            if (string.IsNullOrEmpty(error))
                            {
                                error = _error;
                            }
                            else
                            {
                                error += "\n" + _error;
                            }
                        }

                        if (c == cc)
                        {
                            if (_progress == 1f)
                            {
                                asyncAction(true, 1, error, objs);
                            }
                            else
                            {
                                asyncAction(false, 1, null, null);
                                ResourcesManager.NextFrame(() => {
                                    asyncAction(true, 1, error, objs);
                                });
                            }
                        }
                        return;
                    }

                    _progress = (float)cc / c + 1f / (float)c * progress;
                    asyncAction(false, _progress, null, null);
                });
            }
        }
 /// <summary>
 /// 构造函数
 /// <para>参数 resourcesLoadingLocation 的不同将指示实例对象使用不同的加载方式加载资源; 默认值为 Resources </para>
 /// <para>异常:参数为 Remote 和 StreamingAssets 时,因不支持同步加载资源而抛出异常 。</para>
 /// </summary>
 /// <param name="resourcesLoadingLocation">指示函数加载的位置</param>
 public ResourcesSyncLoader(ResourcesLoadingLocation resourcesLoadingLocation = ResourcesLoadingLocation.Resources)
 {
     switch (resourcesLoadingLocation)
     {
     case ResourcesLoadingLocation.RemotePath:
     case ResourcesLoadingLocation.StreamingAssetsPath:
         var error = KSwordKitName + ": 同步资源加载不能加载 " + resourcesLoadingLocation + " 位置的资源! 请替换 ResourcesAsyncLoader 类进行加载";
         throw new System.ArgumentException(error);
     }
     _resourcesLoadingLocation = resourcesLoadingLocation;
 }
        /// <summary>
        /// 资源管理器的初始化
        /// <para>针对可以直接提供资源清单文本内容的情况</para>
        /// </summary>
        /// <param name="resourcesLoadingLocation">资源加载位置</param>
        /// <param name="resourceslist_jsonString">资源清单的文本内容</param>
        /// <returns>自身实例对象</returns>
        public ResourcesManager Init(ResourcesLoadingLocation resourcesLoadingLocation, string resourceslist_jsonString, System.Action <bool, float, string> initAction = null)
        {
            if (initAction != null)
            {
                Instance.OnInitEvent += initAction;
            }

            if (Instance._isInitializing || _Instance._isInitDone)
            {
                return(Instance);
            }

            Instance._isInitializing = true;
            Instance._isInitDone     = false;
            Instance._initProgress   = 0;
            Instance._initError      = null;

            NextFrame(() => {
                Instance.StartCoroutine(startThreadHandleResourcePackage(resourceslist_jsonString, onInitFunc));
            });
            return(Instance);
        }
        /// <summary>
        /// 初始化资源管理器
        /// <para>默认初始化方式,会从参数指示的位置,按照方法<see cref="GetResourceListFilePath"/>返回的路径进行加载。</para>
        /// </summary>
        /// <param name="resourcesLoadingLocation">加载资源的位置</param>
        /// <returns>自身实例对象</returns>
        public ResourcesManager Init(ResourcesLoadingLocation resourcesLoadingLocation = ResourcesLoadingLocation.Resources, System.Action <bool, float, string> initAction = null)
        {
            if (initAction != null)
            {
                Instance.OnInitEvent += initAction;
            }

            if (Instance._isInitializing || _Instance._isInitDone)
            {
                return(Instance);
            }

            Instance._isInitializing  = true;
            Instance._isInitDone      = false;
            Instance._initProgress    = 0;
            Instance._initError       = null;
            _resourcesLoadingLocation = resourcesLoadingLocation;

            NextFrame(() => {
                Instance.StartCoroutine(loadResourcesList(onInitFunc));
            });

            return(Instance);
        }
        /// <summary>
        /// 资源管理器的初始化
        /// <para>针对提供自定义资源清单文件json数据的加载请求的情况</para>
        /// <para>大多用于资源清单位于服务器的时候</para>
        /// </summary>
        /// <param name="resourcesLoadingLocation">资源加载位置</param>
        /// <param name="resourceslistJsonFileWebRequest">配置好了的加载资源清单json数据的请求对象</param>
        /// <returns>自身实例对象</returns>
        public ResourcesManager Init(ResourcesLoadingLocation resourcesLoadingLocation, UnityEngine.Networking.UnityWebRequest resourceslistJsonFileWebRequest, System.Action <bool, float, string> initAction = null)
        {
            if (initAction != null)
            {
                Instance.OnInitEvent += initAction;
            }

            if (Instance._isInitializing || _Instance._isInitDone)
            {
                return(Instance);
            }

            Instance._isInitializing  = true;
            Instance._isInitDone      = false;
            Instance._initProgress    = 0;
            Instance._initError       = null;
            _resourcesLoadingLocation = resourcesLoadingLocation;

            NextFrame(() => {
                Instance.StartCoroutine(loadResourcesList(resourceslistJsonFileWebRequest, onInitFunc));
            });

            return(Instance);
        }
 /// <summary>
 /// 多个场景异步加载
 /// <para>多场景资源加载完成后,默认不会激活场景;在回调<paramref name="asyncAction"/> 中 SceneInfo 对象可以修改这一操作(泛型类型必须为SceneInfo才支持修改)。</para>
 /// <para>查看<see cref="SceneInfo"/>类内容</para>
 /// </summary>
 /// <param name="assetPaths">场景资源路径</param>
 /// <param name="asyncAction">异步加载回调动作</param>
 public static void LoadSceneAsync(string[] assetPaths, ResourcesLoadingLocation resourcesLoadingLocation, Func <string, AsyncOperation>[] scnenAsyncRequestFuncs, System.Action <bool, float, string, T[]> asyncAction)
 {
     loadAsync(assetPaths, resourcesLoadingLocation, true, scnenAsyncRequestFuncs, asyncAction);
 }
 /// <summary>
 /// 根据资源路径数组 <paramref name="assetPaths"/> 异步加载一组资源
 /// <para>异步加载总比同步的方法慢一帧</para>
 /// <para>参数 <paramref name="asyncAction"/> 是加载资源的异步回调, 回调参数含义为 isDone, progress, error, assets </para>
 /// </summary>
 /// <param name="assetPaths">资源路径</param>
 /// <param name="resourcesLoadingLocation">资源加载位置</param>
 /// <param name="asyncAction">异步回调;参数是异步结果,内部包含进度、错误信息、加载结果等内容。 </param>
 public static void LoadAsync(string[] assetPaths, ResourcesLoadingLocation resourcesLoadingLocation, System.Action <bool, float, string, T[]> asyncAction)
 {
     loadAsync(assetPaths, resourcesLoadingLocation, false, null, asyncAction);
 }
        static void loadAsync(string assetPath, ResourcesLoadingLocation resourcesLoadingLocation, bool isLoadScene, Func <string, AsyncOperation> sceneAsyncRequestFunc, System.Action <bool, float, string, T> asyncAction)
        {
            // 总共需要3步
            // 1. 初始化资源包,只需执行一次
            // 2. 加载资源包
            // 3. 从资源包中加载资源

            // 资源包对象须存在
            if (_ResourcePackage == null)
            {
                if (asyncAction != null)
                {
                    asyncAction(false, 1, null, null);
                    ResourcesManager.NextFrame(() => asyncAction(true, 1, ResourcesManager.KSwordKitName + ": 请先调用 SetResourcePackage 方法设置资源包", null));
                }
                return;
            }
            // 检查缓存内容, 缓存中存在时,加载缓存中的资源
            if (CacheDic.ContainsKey(assetPath))
            {
                if (asyncAction != null)
                {
                    asyncAction(false, 1, null, null);
                    ResourcesManager.NextFrame(() => asyncAction(true, 1, null, CacheDic[assetPath]));
                }

                return;
            }
            // 检查资源是否存在
            if (ResourcesManager.Instance.ResourceObjectPath_ResourceObjectDic.ContainsKey(assetPath))
            {
                var ro = ResourcesManager.Instance.ResourceObjectPath_ResourceObjectDic[assetPath];
                var rm = ResourcesManager.Instance.AssetbundleName_AssetBundlePathDic[ro.AssetBundleName];
                if (ro.IsScene && !isLoadScene)
                {
                    asyncAction(false, 1, null, null);
                    ResourcesManager.NextFrame(
                        () => asyncAction(
                            true,
                            1,
                            ResourcesManager.KSwordKitName + ": 资源加载失败! 该资源是场景资源,但是请求加载非场景资源,因此无法加载! 请使用 `KSwordKit.Contents.ResourcesManagement.ResourcesManager.LoadSceneAsync` 相关的API再次尝试。\n参数 assetPath=" + assetPath,
                            null
                            )
                        );
                    return;
                }
                if (!ro.IsScene && isLoadScene)
                {
                    asyncAction(false, 1, null, null);
                    ResourcesManager.NextFrame(
                        () => asyncAction(
                            true,
                            1,
                            ResourcesManager.KSwordKitName + ": 资源加载失败! 该资源不是场景资源,但是请求加载场景资源,因此无法加载! 请使用 `KSwordKit.Contents.ResourcesManagement.ResourcesManager.LoadAssetAsync` 相关的API再次尝试。\n参数 assetPath=" + assetPath,
                            null
                            )
                        );
                    return;
                }
                // 根据资源加载位置的不同采取不同的加载策略
                switch (resourcesLoadingLocation)
                {
                // 使用 Resources.LoadAsync
                case ResourcesLoadingLocation.Resources:
                    if (ro.IsScene && isLoadScene)
                    {
                        if (!_TypeIsSceneInfo)
                        {
                            Debug.LogWarning(ResourcesManager.KSwordKitName + ": 泛型应当提供类型 `KSwordKit.Contents.ResourcesManagement.SceneInfo`;当前操作将以默认方式继续执行。");
                        }
                        T    _sceneinfo       = null;
                        bool isset__sceneinfo = false;
                        _loader.StartCoroutine(ro.AsyncLoadScene(assetPath, sceneAsyncRequestFunc, (isdone, progress, error, sceneinfo) =>
                        {
                            if (isdone)
                            {
                                asyncAction(isdone, progress, error, _sceneinfo);
                                return;
                            }

                            if (!isset__sceneinfo)
                            {
                                isset__sceneinfo = true;
                                if (_TypeIsSceneInfo)     // 只有在泛型类型为 SceneInfo 时,在回调中的参数 `SceneInfo` 数据才有效。
                                {
                                    _sceneinfo = sceneinfo as T;
                                }
                            }

                            asyncAction(isdone, progress, error, _sceneinfo);
                        }));
                        return;
                    }


                    _loadResourcesByResources(assetPath, asyncAction);
                    break;

                // 其他路径下都使用同样的办法加载资源
                // 加载器只处理本地资源
                // 当使用远程资源时,资源管理器会在需要更新的时候,先更新远程资源到本地,进而保证加载器加载的永远是最新的资源包。
                case ResourcesLoadingLocation.StreamingAssetsPath:
                case ResourcesLoadingLocation.PersistentDataPath:
                case ResourcesLoadingLocation.RemotePath:

                    // 加载资源
                    System.Action abloadedAction = () =>
                    {
                        float _progress = 0;
                        if (ro.IsScene && isLoadScene)
                        {
                            if (!_TypeIsSceneInfo)
                            {
                                Debug.LogWarning(ResourcesManager.KSwordKitName + ": 应当提供类型 `KSwordKit.Contents.ResourcesManagement.SceneInfo`;当前操作将以默认方式继续加载。");
                            }
                            T    _sceneinfo       = null;
                            bool isset__sceneinfo = false;
                            _loader.StartCoroutine(ro.AsyncLoadScene(assetPath, sceneAsyncRequestFunc, (isdone, progress, error, sceneinfo) =>
                            {
                                if (isdone)
                                {
                                    asyncAction(isdone, progress, error, _sceneinfo);
                                    return;
                                }

                                if (!isset__sceneinfo)
                                {
                                    isset__sceneinfo = true;
                                    if (_TypeIsSceneInfo)     // 只有在泛型类型为 SceneInfo 时,在回调中的参数 `SceneInfo` 数据才有效。
                                    {
                                        _sceneinfo = sceneinfo as T;
                                    }
                                }

                                asyncAction(isdone, progress, error, _sceneinfo);
                            }));
                            return;
                        }

                        _loader.StartCoroutine(ro.AsyncLoad(assetPath, rm.AssetBundle, (isdone, progress, error, obj) =>
                        {
                            if (isdone)
                            {
                                System.Action action = () =>
                                {
                                    string asyncLoadAbr_error = null;
                                    try
                                    {
                                        T t = null;
                                        if (_TypeIsSprite)
                                        {
                                            var t2d = obj as Texture2D;
                                            t       = Sprite.Create(t2d, new Rect(0, 0, t2d.width, t2d.height), Vector2.zero) as T;
                                        }
                                        else
                                        {
                                            t = obj as T;
                                        }

                                        if (t != null)
                                        {
                                            // 资源加载成功后,存入资源缓存中
                                            CacheDic[assetPath] = t;
                                            asyncAction(true, 1, null, t);
                                        }
                                        else
                                        {
                                            asyncLoadAbr_error = ResourcesManager.KSwordKitName + ": 资源加载成功,但该资源无法转换为 " + _Type.FullName + " 类型。\nassetPath=" + assetPath;
                                            asyncAction(true, 1, asyncLoadAbr_error, null);
                                        }
                                    }
                                    catch (System.Exception e)
                                    {
                                        asyncLoadAbr_error = ResourcesManager.KSwordKitName + ": 资源加载成功,但该资源无法转换为 " + _Type.FullName + " 类型, " + e.Message + "\nassetPath=" + assetPath;;
                                        asyncAction(true, 1, asyncLoadAbr_error, null);
                                    }
                                };
                                if (_progress != 1)
                                {
                                    if (asyncAction != null)
                                    {
                                        asyncAction(false, 1, error, null);
                                    }
                                    ResourcesManager.NextFrame(action);
                                }
                                else
                                {
                                    action();
                                }

                                return;
                            }

                            _progress = 2f / 3f + 1f / 3f * progress;
                            if (asyncAction != null && _progress > 2f / 3f)
                            {
                                asyncAction(false, _progress, error, null);
                            }
                        }));
                    };

                    if (rm.AssetBundle == null)
                    {
                        // 加载资源包
                        rm.AsyncLoadTimeout = timeoutIfCanBeApplied;
                        _loader.StartCoroutine(rm.AsyncLoad((isdone, progress, error, obj) =>
                        {
                            if (isdone)
                            {
                                if (string.IsNullOrEmpty(error))
                                {
                                    if (asyncAction != null)
                                    {
                                        asyncAction(false, 2f / 3f, null, null);
                                    }
                                    abloadedAction();
                                }
                                else if (asyncAction != null)
                                {
                                    asyncAction(false, 1, error, null);
                                }

                                return;
                            }
                            if (asyncAction != null)
                            {
                                asyncAction(false, 1f / 3f + 1f / 3f * progress, error, null);
                            }
                        }));
                    }
                    else
                    {
                        abloadedAction();
                    }
                    break;
                }
            }
            else
            {
                if (asyncAction != null)
                {
                    asyncAction(false, 1, null, null);
                    ResourcesManager.NextFrame(() => asyncAction(true, 1, ResourcesManager.KSwordKitName + ": 资源不存在!请检查参数 assetPath 是否正确,assetPath=" + assetPath, null));
                }
            }
        }