语雀地址
热更资源加载部分想使用91焦先生的 BundleMaster UI部分又想使用QFramework的Ui框架 所以对QF的UIkit加载UIPanel资源部分自定义
自定义PanelLoader 意味着 不会具有通过传入的prefabName 前缀匹配对应ResLoader的功能 (这种更适合我 )因为不是使用QF提供的ResLoader加载资源(可以查看ResKitPanelLoaderPool)
没这种功能
采用下面这两种写法
其他方式可以自己拓展
自行配置BundleMaster相关
编写自定义的加载方式进行替换
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创建一个测试面板
使用
可以正常显示
加载方式通过BM来控制
开发模式加载 然后切换BM资源加载模式为开发模式
AB加载
配置一下分包
先打AB包 然后切换BM资源加载模式为本地模式 copyab资源到StreamingAssets文件夹
然后运行
进入UIkit脚本中的OpenPanel
panelSearchKeys.PanelType 记录了测试面板脚本的类型 QFramework.UITestBMResPanel
panelSearchKeys.GameObjName 记录的预制体全路径
通过这两个字段 就可以知道要加载的UI预制体名字和所在的位置
进入UIManager.Instance.OpenUI(panelSearchKeys)这个方法
可以看到在检测到这个面板没被创建的时候会创建一个新的面板
这里跳转到了 var panel = UIKit.Config.LoadPanel(panelSearchKeys); 这个方法
进入UIKitConfig.cs后
可以看到 有一个叫做PanelLoaderPool的字段 这个就是用来存储加载器的加载器池子
找到LoadPanel方法可以看到 池子分配了一个加载起出来
在这个UIKitWithResKitInit中是启动后默认的加载方式
这句话会使方法在场景加载之前执行 意味着UIKitConfig.PanelLoaderPool 会指向这个加载器
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
往下翻可以看到IPanelLoade上凉鞋的注释 很贴心
所以只需要继承IPanelLoader仿照ResKitPanelLoaderPool写一个自己的加载器实现一下同步加载资源和异步加载资源就行了