| name | xforge-manual |
| description | Detailed documentation and usage guide for the XForge framework. Invoke when implementing features, checking API usage, or needing examples for modules, services, models, views, or built-in tools. |
XForge Framework Manual
📚 1. 快速入门与目录结构
1.1 项目概览
- ⚡ 框架名称: XForge
- 🛠️ 引擎版本: Cocos Creator 3.8
- 🧩 核心路径:
extensions/xforge/runtime/ (框架源码)
- 📦 扩展路径:
extensions/pkg/ (扩展包插件)
- 🎮 业务路径:
assets/ (游戏逻辑)
1.2 目录规范 (assets/)
项目采用模块化设计,主要分为四类目录:
| 目录 | 说明 | 关键文件/用途 |
|---|
assets/app | 全局入口 | app.ts (静态数据), main/Main.ts (启动脚本) |
assets/app-global | 全局模块 | 通用功能(如通用弹窗等)。代码在 assembly/,资源在 assetbundle/。 |
assets/app-module | 功能模块 | 独立功能(如 Home, Battle)。代码在 assembly/,资源在 assetbundle/。 |
assets/app-shared | 共享资源 | 存放全局通用的代码和资源。代码在 assemblies/,资源在 assetbundles/。 |
📁 模块内部结构与命名规范对比
全局模块 (app-global) 与功能模块 (app-module) 逻辑结构一致,但命名习惯有别:
| 层级/功能 | 全局模块 (app-global) | 功能模块 (app-module) |
|---|
| 物理路径 | assets/app-global/ | assets/app-module/[ModuleName]/ |
| 入口文件 | assembly/AppGlobal.ts | assembly/AppModule[Name].ts |
| 装饰器 | @global | @module('[Name]') |
| 继承父类 | BaseModule | BaseModule |
| UI 组件 | assembly/global-view/ | assembly/module-view/ |
| 数据模型 | assembly/global-model/ | assembly/module-model/ |
| 业务逻辑 | assembly/global-service/ | assembly/module-service/ |
| 资源-View | assetbundle/global-view/ | assetbundle/module-view/ |
| 资源-Sound | assetbundle/global-sound/ | assetbundle/module-sound/ |
💡 注意: app-module 下需先创建模块名文件夹(如 Home),再建立 assembly 和 assetbundle。
⚠️ 1.3 AssetBundle 与脚本引用规范
模块下的 assembly (代码) 和 assetbundle (资源) 目录在 Cocos Creator 中都被配置为 AssetBundle。
- 动态加载: 这些 AssetBundle 是在运行时按需动态加载的。
- 引用顺序限制: 严禁出现“先加载的 AssetBundle (如
app-global) 引用后加载的 AssetBundle (如 app-module/Home) 中的脚本”。
- ❌ 错误:
AppGlobal 引用 HomeService。
- ✅ 正确:
HomeService 引用 AppGlobal (下层引用上层)。
1.4 菜单工具
框架中的模块、服务、模型、视图、音乐音效等的创建都需要通过菜单工具来完成。
- 模块: 菜单 -> XForge -> 创建 -> 选择Module或Global标签 -> 输入名字(Global不需要) -> 创建
- 服务: 菜单 -> XForge -> 创建 -> 选中目标模块 -> 创建Service -> 输入名字 -> 创建
- 模型: 菜单 -> XForge -> 创建 -> 选中目标模块 -> 创建Model -> 输入名字 -> 创建
- 视图: 菜单 -> XForge -> 创建 -> 选中目标模块 -> 创建View -> 输入名字 -> 创建
- 音乐音效: 菜单 -> XForge -> 创建 -> 选中目标模块 -> 创建Sound -> 输入名字 -> 创建
1.5 全局访问对象 (app)
框架导出了全局变量 app (extensions/xforge/runtime/XForge.ts):
app.lib: 内置工具箱。
app.global: 访问全局模块实例 (单例)。
app.loadModule / app.unloadModule: 加载/卸载功能模块。
- 注意:
app 对象不提供获取功能模块实例的 API。功能模块实例仅能在其内部组件中通过 this.module 访问,以保证解耦。
1.6 共享资源区 (app-shared)
assets/app-shared 是共享的核心目录,包含两个子目录:
assets/app-shared/assemblies/:存储需要共享的代码。
assets/app-shared/assetbundles/:存储自定义的AB包资源。
⚠️ 注意:app-shared 也可以不需要时删除此文件夹。
🚀 2. 启动流程
启动流程主要由 assets/app/main/Main.ts 控制。
⚠️ 约束: 项目启动场景必须设置为 Main(Main.scene), 否则会导致运行时错误(如报框架层面的属性为undefined等错误信息)。
Main.ts 的核心职责:
- 🛠️ 初始化: 必须优先调用父类
setup() 方法进行框架初始化。
- 🖼️ 闪屏逻辑: 处理启动画面的显示与销毁。
- 🔄 热更新: (可选) 检查并执行资源热更新。
启动步骤示例:
protected start(): void {
this.setup();
app.lib.task.createSync()
.add(next => {
app.loadGlobal({ onLoaded: next });
})
.add(next => {
app.loadModule({ name: 'Home', onLoaded: next });
})
.start(() => {
this.splashScreen.destroy();
});
}
💡 提示: 启动逻辑不强制要求写在 start 中,onLoad 或 onEnable 亦可,但务必保证在进行任何业务操作前先调用 this.setup()。
📦 3. 模块层 (Module)
模块是核心组织单位,所有业务逻辑都必须归属于某个模块。
3.1 模块定义与基类
所有模块入口脚本都继承自 BaseModule,并使用装饰器标记。
import { BaseModule, module } from 'db://xforge/base/BaseModule';
@module('Home')
export class AppModuleHome extends BaseModule { ... }
import { BaseModule, global } from 'db://xforge/base/BaseModule';
@global()
export class AppGlobal extends BaseModule { ... }
3.2 模块生命周期
init(onLoaded, onError, onProgress): 模块初始化(异步)。
onLoad(): 模块加载完成。
onUnload(): 模块卸载。
3.3 ⚠️ 初始化最佳实践 (防黑屏)
为了避免模块切换过程中出现黑屏,必须在 init 中调用 ui.show 并等待 onShow 回调后再执行 onLoaded()。
protected init(onLoaded: () => void, onError: () => void, onProgress: (result: number) => void): void {
this.ui.show({
view: PageHome,
onShow: onLoaded,
onError: onError,
onProgress: onProgress
});
}
3.4 UI 管理 (UIManager)
模块提供了 ui 对象用于管理界面显示。
this.ui.show({
view: PageHome,
data: { id: 1 },
onShow: () => console.log('Opened'),
onHide: () => console.log('Closed')
});
3.5 音乐音效 (SoundManager)
模块提供了 sound 对象用于管理音频。
this.sound.playMusic('bgm/main');
this.sound.playEffect('ui/click');
- 路径相对于
music/ 或 effect/ 目录。
3.6 组件获取 (Model/Service)
在模块内部的 Model/Service/View 中,可以通过 this.module 获取当前模块的 Model 和 Service 实例。
const gameModel = this.module.useModel(GameModel);
const gameService = this.module.useService(GameService);
3.7 模块访问约束
- 功能模块访问: 仅能在 Model/Service/View 中通过 this.module 访问当前模块。因初始化顺序问题,在View的onLoad函数中无法使用this.module。
- 全局模块访问: 通过 app.global 获取全局模块实例。
- 禁止: 跨模块直接持有其他功能模块实例,或在模块外部获取功能模块实例。
💾 4. 数据层 (Model)
Model 负责数据的存储、运算和校验,推荐结合 cc-store 实现响应式更新。
4.1 定义与基类
继承自 BaseModel。如果需要响应式能力,需在构造函数返回 createStore(this)。
import { BaseModel } from 'db://xforge/base/BaseModel';
import { IModelContext } from 'db://xforge/base/BaseModule';
import { createStore } from 'db://pkg/@gamex/cc-store';
export class GameData extends BaseModel {
constructor(module: IModelContext) {
super(module);
return createStore(this);
}
score = 0;
}
4.2 职责边界
- 持有模块数据。
- 纯数据运算与校验。
- 网络请求: 允许发起纯数据类请求(如登录、配置拉取),并将结果存入自身。涉及复杂业务逻辑的请求仍建议由 Service 编排。
- 禁止引入
cc.Node 等渲染类。
4.3 获取方式
在同模块的 Service/View 中:
const gameData = this.module.useModel(GameData);
⚙️ 5. 服务层 (Service)
Service 是模块的“大脑”,负责业务逻辑编排和跨组件通信。
5.1 定义与基类
继承自 BaseService。
import { BaseService } from 'db://xforge/base/BaseService';
export class GameService extends BaseService { ... }
5.2 职责边界
- 业务编排: 协调 Model、Network、UI。
- 通信桥梁: 负责模块内组件交互;跨模块通信需借助全局模块 Service 实现。
- 无状态: 禁止持有 UI 组件引用 (
cc.Node)。
5.3 消息通信 (MessageBus)
每个 Service 实例自带 event 属性。
⚠️ 严格约束:
- 同文件定义: Event 类必须定义在 Service 类的同一个文件中。
- 私有化范围: Service 只能发送(emit)它自己文件中定义的 Event。
export class LoginEvent implements MessageBus.IEvent { ... }
export class GameService extends BaseService {
login() {
this.event.emit(new LoginEvent());
}
}
🎨 6. 视图层 (View)
View 负责界面展示和交互,推荐使用 MVVM 模式。
6.1 定义与基类
继承自 BaseView。
6.2 View 类型
- Page: 场景级大界面 (对应资源: Scene)。
- Paper: 页面拆分组件 (对应资源: Prefab)。
- Pop: 业务弹窗 (对应资源: Prefab)。
- Top: 顶层系统弹窗 (对应资源: Prefab)。
6.3 生命周期
static beforeShow(module, data): (静态方法/异步) 视图显示前的预加载阶段。
onLoad(): 节点首次初始化时触发(引擎原生)。
onShow(data): 视图每次显示时触发,接收外部传入的数据。
beforeHide(): 视图隐藏前触发。
onHide(): 视图隐藏后触发。
限制:beforeShow中不要调用module.ui.show,避免show流程卡死
6.4 数据绑定 (MVVM)
使用 cc-store 将 View 与 Model 绑定。
import { bindStore, watchStore, stopWatch } from 'db://pkg/@gamex/cc-store';
export class PageGame extends BaseView {
onShow() {
const gameData = this.module.useModel(GameData);
bindStore(this.label, 'string', () => `Score: ${gameData.score}`);
watchStore(this.onScoreChange, this);
}
onHide() {
stopWatch(this.onScoreChange, this);
}
}
6.5 视图属性配置
在 View 的脚本组件中,可以配置以下重要属性:
- hideMode:
ViewHideMode.Active: 仅设置 node.active = false。保留节点内存,再次打开速度快。
ViewHideMode.Destroy: 销毁节点。节省内存,但重新打开需要重新实例化。
- shade:
- 为true时,会在 UI 下方自动生成一个黑色半透明遮罩(常用于 Pop 或 Top 类型)。
6.6 职责边界
- 处理交互、动画、数据绑定。
- 允许包含 UI 强相关的轻量业务逻辑。
- 重度逻辑应下沉至 Service。
🛠️ 7. 内置工具库 (Tools)
位于 app.lib 命名空间下。
- Storage:
app.lib.storage.set('key', 'val') / setDay (按天存储)。
- Task:
app.lib.task.createSync() 串行任务队列。
- Loader: AB 资源加载有两种方式:
app.lib.loader(全局加载器):app.lib.loader.loadBundleAsync({bundle}) / app.lib.loader.loadAssetAsync({path, type}) / app.lib.loader.loadDirAsync({path, type}),需手动指定 bundle 名。
BaseModule 实例方法(模块内使用):this.module.loadAsset(path, type, onComplete) / this.module.loadDir(path, type, onComplete),自动使用当前模块的 BundleName,无需手动指定。
- Logger:
app.lib.logger.log/warn/error。
- Debug:
app.lib.debug.unobservable。
🤖 8. AI 编码原则与限制 (CRITICAL)
- API 真实性: 严禁臆造 API。必须基于
extensions/xforge/runtime/ 源码。
- 模块安全: 禁止跨模块直接引用 Model/Service。
- View 安全: 禁止自动创建/修改 Prefab/Scene 文件。
- 纯洁性: Model/Service 禁止持有
cc.Node 等渲染类组件。
- 优先复用: 优先使用
app.lib 工具链。
📦 9. 扩展包管理
所有扩展包安装在 extensions/pkg/。
- 安装:
node extensions/pkg/index.js add <package-name>
- 引用:
import ... from 'db://pkg/<package-name>'
框架基于 npm 管理,但建议仅使用以下经过框架适配的官方扩展包:
🔹 核心模块
| 包名 | 说明 |
|---|
@gamex/cc-expand | 属性扩展: node.x、node.scaleX等 |
@gamex/cc-store | 状态管理,数据变化自动更新UI |
@gamex/cc-request | POST/GET网络请求 |
@gamex/cc-number | 防内存挂数字类型 |
@gamex/cc-random | 种子随机 |
@gamex/cc-astar | A星巡路,支持4/6/8方向及路径平滑 |
@gamex/cc-quadtree | 四叉碰撞树 |
@gamex/cc-sap | SAP碰撞检测 |
@gamex/cc-sat | SAT碰撞检测 |
@gamex/cc-rvo2 | 动态避障 |
@gamex/cc-ecs | 实体-组件-系统 |
@gamex/cc-emath | 精确数学运算,替换原生Math下三角函数运算并添加随机种子能力 |
@gamex/cc-decimal | 定点数学运算 |
@gamex/cc-decimal-vec2 | 定点数二维向量 |
@gamex/cc-decimal-vec3 | 定点数三维向量 |
@gamex/cc-decimal-sat | 定点数SAT碰撞检测 |
@gamex/cc-decimal-sap | 定点数SAP碰撞检测 |
@gamex/cc-decimal-random | 定点数随机 |
@gamex/cc-xml-parser | XML解析 |
@gamex/cc-minisdk | 小游戏SDK模块 |
🔹 UI 组件
| 包名 | 说明 |
|---|
@gamex/cc-comp-toggle | Toggle组件 |
@gamex/cc-comp-rich-text | RichText组件 |
@gamex/cc-comp-spring-arm | 弹簧臂组件 |
@gamex/cc-comp-animation | Animation组件 |
@gamex/cc-comp-skeleton | Spine组件 |
@gamex/cc-comp-skeletal-animation | 3D骨骼动画组件 |
@gamex/cc-comp-movie-animation | MovieClip播放组件 |
@gamex/cc-comp-frame-animation | 帧动画播放组件 |
@gamex/cc-comp-rewardfly | 奖励飞行动画组件 |
🔹 UI 控件
| 包名 | 说明 |
|---|
@gamex/cc-ctrl-toast | 消息提示控件 |
@gamex/cc-ctrl-rocker | 摇杆控件 |