CocosCreatorUI框架分享 -- honmono

框架地址: https://github.com/kirikayakazuto/CocosCreator_UIFrameWork

这个框架第一次提交在2019年7A31708E-67CF-4F20-9C36-C8BA7C6C6A5F
目前已经有300+次提交了 88B05144-B497-489F-BAD5-9661E70F024A :grinning:
最开始做这个框架的时候我还在学校 :joy: 所以希望大家多提建议, 多多指教.

注意! 本框架是个人开发, 用于商业开发前建议先做一下评估.

基于cocos creator的UI框架, 使用过程中有任何问题,可以加QQ群: 552424835

当前使用的cocos creator版本2.4.8版本. 理论上支持2.2.x ~ 2.4.x的所有版本. 3d版本目前在开发中… 尽请期待

0, 简单介绍

基于Cocos Creator的UI框架, 采用单场景+多预制体模式. 界面中的窗体都按需加载, 复用性高. 使用者只需要关心界面内的逻辑, 其他的
场景切换, 弹窗管理, 资源管理都可以交给框架.

对于游戏中的窗体, 可以大致分为4类.

  • Screen
  • Fixed
  • Window
  • Tips

以下图为例

Screen可以理解为场景, 一般是会铺满屏幕. 如上图黄色框中的地图.

Fixed则是一下固定在场景屏幕边缘的功能性UI, 如上图红色框中的两个按钮.

Window则是游戏中的各种弹出窗体, 一般会有一个弹出动画. 如上图蓝色框中的面板.

Tips则是一些提示性窗体, 比如断线提示窗体. 这种窗体的特点是不受其他窗体的影响, 只管自己显示和隐藏.

tips: Screen窗体切换时会隐藏当前显示的Fixed, Window窗体, 以到达切换场景的效果.

1. 项目结构

  • AutoScripts: 是插件AutoBinder生成的代码. (待实现: 自动清理未被使用的文件)
  • Common: 一些公共的脚本文件, 有工具类, 和一些封装好的组件.
  • Logic: 用户自定义的管理类, 如ConfigMgr
  • types: 提供wx小游戏的api提示
  • UIFrame: 框架核心脚本
  • UIScript: 用户自定义的界面控制脚本
  • Main.ts: 类似入口脚本

2. 启动流程

打开Main场景, 在结点树上可以看到有一个Scene结点

Scene结点很关键, 它作为框架的UI层级的父节点, 所以如果你有其他独立与UI框架的层级的需求时,可以根据Scene结点的层级做调整.

Scene结点上挂载了Scene脚本, 打开这个脚本可以看到onGameInit方法, 这个方法控制游戏的初始化流程. 流程如下

// 第一步 展示loading页面,当然有些默认就是loading页面, 可以把loading界面做在场景中, 遮挡住Scene结点.

// 第二步 初始化游戏(Managers,Configs,SDKs)
await Game.init(this.node);
// 第三步 构建初始场景(加载必要的prefab,音频,texture)
await ResMgr.loadRes() 或者 await UIManager.getInstance().loadForm() 等等
// 第四步 加载主界面UI,关掉loading页面,正式进入游戏
await SceneMgr.open("");
this.loading.destory();// 假设你已经获取到了loading ui

Game.ts脚本则是作为游戏的逻辑层控制器. 打开可以开到init方法, 这个方法控制游戏内控制器的初始化.

// 初始化Manager, 例如new ConfigMgr();
this.configMgr = new ConfigMgr();
this.playerMgr = new PlayerMgr();
// 初始化平台sdk

// 加载配置信息, 因为在这里就已经加装完毕配置信息了, 所以后面加装主界面UI时, 就可以读取相关配置了
await this.configMgr.loadConfigs();

Game.ts脚本还可以控制逻辑控制器的时间更新, 打开update方法.

if(!this.inited) return ;
Task.update(dt); // 更新任务进度

3. 框架结构

采用UIBase + UIManager两个核心类管理整个框架, 其他的Manager辅助UIManager进行管理.

UIBase篇

UIBase中定义窗体的属性和一系列的生命周期方法

formType: FormType;           // 窗体类型
willDestory: bool;            // 是否会被销毁, 只有这个标记为true时, 关闭窗体时才会销毁这个窗体, 不然就是隐藏

实际项目中不要直接继承UIBase, 请继承它的子类 UIScreen, UIFixed, UIWindow, UITips. 子类中预实现了一些功能.

生命周期方法

async load(): string;                         // 只调用一次, 异步方法, 返回一个错误信息.
onInit(): void;                               // 只调用一次, 初始化.
onShow(): void;                               // 每次显示时调用.
onload(): void;                               // cocos提供
start(): void;                                // cocos提供
onAfterShow(): void;                          // 显示动画结束后调用
onHide(): void;                               // 隐藏时调用
onAfterHide(): void;                          // 隐藏动画结束后调用
onDestory(): void;                            // cocos提供

显示和隐藏动画, 使用者可以重写下面两个方法, 实现自定义的显示隐藏动画.

async showEffect(): void;                      // 窗体显示动画
async hideEffect(): void;                      // 窗体隐藏动画

UIManager篇

UIManager在getInstance()时, 会自动的创建UIROOT和四个子节点. 结构如下图

这四个子节点对应的UIBase中的四种类型, 对应类型的窗体会被挂载到对应结点下.

UIManager只暴露的四个接口.

loadForm(path: string): UIBase;                                       // 预加载窗体
openForm(path: string, param: any, formData: IFormData): UIBase;      // 打开窗体
closeForm(path: string): UIBase;                                      // 隐藏窗体
getForm(path: string): UIBase;                                        // 获得窗体

UIManager在打开窗体时, 会获取窗体上的UIBase组件, 然后根据类型, 将窗体挂载到不同的node上. 然后触发UIBase中的
生命周期方法.

UIManager内部控制流程如下图…

loadForm和openForm复用同一个加装回调, 所以不用担心预加载窗体后, 还没等预加载结束就调用openForm导致的加装浪费.

其他Manager

WindowMgr 窗体控制器

UIManager中其实已经通过栈结构实现了简单的窗体控制, 但是对于一些复杂的控制效果, 则交给WindowMgr实现.
比如优先栈和等待栈, 优先栈指的 每一个窗体有一个优先级, 根据优先级的不同在优先栈会有不同的排序效果, 从而影响窗体弹出顺序.
等待栈指的

WindowMgr.open(prefabPath: string, params?: any, formData: IFormData = {showWait: false, priority: EPriority.FIVE});														 // 打开, formData中 showWait表示是否进入等待队列, priority表示优先级.
WindowMgr.close(prefabPath: string);					// 关闭

SceneMgr 场景控制器

// 打开场景
SceneMgr.open(scenePath: string, params?: any, formData?: IFormData);
// 退回上一个场景
SceneMgr.back(params?: any, formData?: IFormData);

ResMgr 资源控制器

ResMgr管理窗体的资源, 恪守 我释放的是我加载的资源, 我加载的资源会被释放.

不建议用户直接使用这个Manager. 里面主要是加载窗体,和动态资源.

ResMgr.inst.loadDynamicRes(url: string, type: typeof cc.Asset, tag: string);		// 加载动态资源, 内部使用
// 上面的方法请通过这个方法调用 UIBase.loadRes(url: string, type?: typeof cc.Asset);														

AdapterMgr 适配控制器

对窗体进行位置适配, 比如对于screen类型的窗体, 框架默认为它添加了全屏的适配, 如下

AdapterMgr.inst.adapteByType(AdapterType.StretchHeight | AdapterType.StretchWidth, this.node);

todo… 做成可视化组件

4 .插件和demo, 都是我日常开发中觉得可以提高开发效率的一些产品和尝试

自动生成UIConfig插件 AutoConfig

快捷键 alt + f

UIConfig文件里除存储的是UI名称和UI路径的关系, 现在可以自动生成UIConfig文件了.

自动绑定结点插件 AutoBinder

快捷键 alt + g

根据规范的命名规则实现代码自动生成和结点绑定

如: _Label$Name

_ 下划线表示这个结点是需要被绑定的

Label 表示属性的类型, 支持自定义组件, 命名映射可以修改

$ 分隔符

Name 属性名称

通过Alt + g就会自动生成

@property(cc.Label) Name: cc.Label = null;的代码

然后将脚本挂载在根节点上, 在将_Label$Name结点绑定在组件上

状态控制器 PropController

类似fgui中的状态控制器, 已经在实际项目中使用过, 状态控制只需一行代码. 支持自定义脚本的自定义属性.

视频介绍: Cocos Creator 状态控制器_哔哩哔哩_bilibili

更新了2dlight, 实现了取反的阴影效果

更新了画板, 可以在图片上绘制图案, 擦除颜色等

2021/01/31 Binder plus, 升级了项目中的自动结点绑定

注意: 目前第一次生成脚本时无法立即绑定到对应结点上, 需要再次执行一次run 即可.

支持代码生成和结点绑定

2020/10/19 Mask Plus, 支持自定义遮罩

扩展了cc.Mask, 添加了一种枚举类型Polygon

2020/10/15 添加2d光线功能

2d光影效果, 项目在2dlight分支, 目前还在优化中 关键代码在Script/Common/light下, 有兴趣的可以看看

2020/7/28 集成ECharts

集成了ECharts, 在ECharts-Support分支, 有需要的可以看看

2020/7/10 新增功能

集成Mobx,对于Mobx的使用详情可以前往Mobx的官网了解,github地址 https://github.com/mobxjs/mobx

对于cocos使用例子可以看项目中UIHall的实现

注意事项:将mobx导入为插件时需要将允许编辑器加载打上勾:white_check_mark:

11赞

天尊无敌 dddd

天尊yyds!!!

H佬有一点骚!!!

天尊无敌 dddd

天尊永远最骚!!!

天尊yyds!!!

天尊,你好骚啊~~

天尊永远最骚!!!

error: Error: Malformed UTF-8 data
读取数据的时候报这个错 怎么搞?

虽然已从ccc顺利转到了UE4,还是大力支持楼主的技术分享~太厉害了 :+1: :+1:

先MARK再看

扫了一眼,可以哎 不错

天尊无敌啊,已经用天尊的框架试写过一款小游戏了,生产力拉满

怎么可以这么牛

mark 定位一下

战术性马克一下mark

有多honmono?

666666666 :10: