使用BundleMaster替换QFramework中UiKit面板资源加载方式

 语雀地址

热更资源加载部分想使用91焦先生的 BundleMaster UI部分又想使用QFramework的Ui框架 所以对QF的UIkit加载UIPanel资源部分自定义

注:

自定义PanelLoader 意味着 不会具有通过传入的prefabName 前缀匹配对应ResLoader的功能 (这种更适合我 )因为不是使用QF提供的ResLoader加载资源(可以查看ResKitPanelLoaderPool)

没这种功能

采用下面这两种写法

其他方式可以自己拓展

UI预制体的存放位置限制

  • 如果使用不填写prefabName的方式 只能存放在"Assets/Bundles/UIPrefab/"目录下 不能嵌套层级(想要嵌套层级的话 可以按照名字和路径进行存储 搜集到一个文件里 然后通过名字匹配查找到指定路径 在加载)
  • 如果使用填写prefabName的方式 UI预制体层级随便放

自行导入BundleMaster

自行配置BundleMaster相关

一 直接使用

编写自定义的加载方式进行替换

  1. 找个地方存放下面这个脚本
  2. 然后把UIKitWithResKitInit.cs中 Init上的特性给注释了

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第1张图片

using System;
using BM;
using UnityEngine;
using Object = UnityEngine.Object;

namespace QFramework
{
    public class UIKitWithBMInit
    {
        
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        public static void Init()
        {
            UIKit.Config.PanelLoaderPool = new BMPanelLoaderPool();
        }
    }
    public class BMPanelLoaderPool : AbstractPanelLoaderPool
    {
       
        public class BMPanelLoader : IPanelLoader
        {
            private LoadHandler _loadHandler;

            private string uiABRootPath="Assets/Bundles/UIPrefab/";
            /// 
            /// 传递UI预制体的完整路径   GameObjName   不使用全路径的话  UI必须放到"Assets/Bundles/UIWindow/目录下
            /// 
            /// 
            /// 
            public GameObject LoadPanelPrefab(PanelSearchKeys panelSearchKeys)
            {
                if (_loadHandler != null)
                {
                    return (_loadHandler.Asset) as GameObject;
                }

                if (string.IsNullOrEmpty(panelSearchKeys.GameObjName) && panelSearchKeys.PanelType != null)
                {
                    string nameFullPath = $"{uiABRootPath}{panelSearchKeys.PanelType.Name}.prefab";
                    return AssetComponent.Load(out _loadHandler, nameFullPath);
                }

                return AssetComponent.Load(out _loadHandler, panelSearchKeys.GameObjName);
            }

            public void LoadPanelPrefabAsync(PanelSearchKeys panelSearchKeys, Action onLoad)
            {
                if (_loadHandler != null)
                {
                    // return (_loadHandler.Asset) as GameObject;
                    onLoad?.Invoke((_loadHandler.Asset) as GameObject);
                    return;
                }

                if (string.IsNullOrEmpty(panelSearchKeys.GameObjName) && panelSearchKeys.PanelType != null)
                {
                    string nameFullPath = $"{uiABRootPath}{panelSearchKeys.PanelType.Name}.prefab";
                    AssetComponent.LoadAsync(out _loadHandler, nameFullPath);
                    _loadHandler.Completed += (result) => { onLoad?.Invoke((result.Asset) as GameObject); };
                    return;
                }

                AssetComponent.Load(out _loadHandler, panelSearchKeys.GameObjName);
                _loadHandler.Completed += (result) => { onLoad?.Invoke((result.Asset) as GameObject); };
            }

            public void Unload()
            {
                _loadHandler.UnLoad();
                _loadHandler = null;
            }
        }

        protected override IPanelLoader CreatePanelLoader()
        {
            return new BMPanelLoader();
        }
    }
}

先使用UIPanel创建一个测试面板

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第2张图片

使用

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第3张图片

可以正常显示

加载方式通过BM来控制

开发模式加载 然后切换BM资源加载模式为开发模式

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第4张图片

AB加载

配置一下分包

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第5张图片

先打AB包 然后切换BM资源加载模式为本地模式 copyab资源到StreamingAssets文件夹

然后运行

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第6张图片

二 分析

分析

进入UIkit脚本中的OpenPanel方法可以发现

panelSearchKeys.PanelType 记录了测试面板脚本的类型 QFramework.UITestBMResPanel

panelSearchKeys.GameObjName 记录的预制体全路径

通过这两个字段 就可以知道要加载的UI预制体名字和所在的位置

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第7张图片

进入UIManager.Instance.OpenUI(panelSearchKeys)这个方法

可以看到在检测到这个面板没被创建的时候会创建一个新的面板

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第8张图片

这里跳转到了 var panel = UIKit.Config.LoadPanel(panelSearchKeys); 这个方法

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第9张图片

进入UIKitConfig.cs后

可以看到 有一个叫做PanelLoaderPool的字段 这个就是用来存储加载器的加载器池子

找到LoadPanel方法可以看到 池子分配了一个加载起出来

默认的加载器 ResKitPanelLoader

在这个UIKitWithResKitInit中是启动后默认的加载方式

这句话会使方法在场景加载之前执行 意味着UIKitConfig.PanelLoaderPool 会指向这个加载器

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第10张图片

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第11张图片

关于加载器

往下翻可以看到IPanelLoade上凉鞋的注释 很贴心

所以只需要继承IPanelLoader仿照ResKitPanelLoaderPool写一个自己的加载器实现一下同步加载资源和异步加载资源就行了

使用BundleMaster替换QFramework中UiKit面板资源加载方式_第12张图片

你可能感兴趣的:(Unity,unity)