# 单游戏构建操作 返回[构建目录](README.md)。关联文档:[版本配置](version-and-build.md)、[子游戏接入](../integration/README.md)。核对日期:2026-09-09,Cocos Creator 3.8.8。 ## 1. 当前能力与边界 一个 YouleNexus 工程可以包含多个子游戏。公共 app/framework/scripts 不静态导入具体子游戏,启动时按 `gameKey` 加载目标游戏 Bundle 的入口,并加载该游戏的创建页面和房间 prefab。 构建时使用 Creator 自身的 Bundle 选择能力,使未选游戏的代码和资源不进入产物。不修改引擎源码,不先构建全部游戏再手动删除。 **目前需要配合完成两项选择:保存启动场景的 gameKey;在构建面板勾选对应的 Bundle。两者尚未自动同步。** 修改 gameKey 不会自动改变构建面板,导入构建配置也不会修改场景 gameKey。 当前真实验收范围是二七王 Web Mobile:产物无模板游戏实现及私有资源,导出网页进入登录页,二七王创建页与房间 prefab 可实例化,XML 版本正确。此结果不代表完整牌局、服务器重连或原生壳已重新验收。模板的同类步骤如下,但不能将独立实验工程的双向验证当作两款正式游戏均已完成导出运行验收。 ## 2. 一次性资源准备 以下位置均以 YouleNexus 工程为基准。资源元数据、prefab 和场景使用编辑器配置;AI 操作走 Cocos MCP,不手改序列化文件。 公共 `assets/resources` 包名为 `resources`,当前优先级 8,包含 `dev-config` 等公共运行资源。它不是任何一款子游戏的私有目录,当前开发构建必须保留。 二七王的配置: - 游戏目录:`assets/games/erqiwang`;包名 `game-erqiwang`;优先级 **1**。 - 版本目录:`assets/games/erqiwang/resources`;包名 `version-erqiwang`;优先级 **2**。 - 入口类名:`GameEntry_erqiwang`;static definition 提供本游戏定义。 - 版本资源:`assets/games/erqiwang/resources/erqiwang/version.xml`。 模板的配置: - 游戏目录:`assets/games/template`;包名 `game-Game_Surface_3`;优先级 **1**。 - 版本目录:`assets/games/template/resources`;包名 `version-Game_Surface_3`;优先级 **2**。 - 入口类名:`GameEntry_Game_Surface_3`。 - 版本资源:`assets/games/template/resources/Game_Surface_3/version.xml`。 **版本包优先级必须高于游戏根包。** 两者相同时,嵌套 XML 可能被父包收走,产生“版本包存在,但包内没有 version”的错误。修正元数据归属,不增加另一条运行时加载路径。 新增或移动脚本后,确认编辑器完成导入,资源数据库能查到脚本且已生成 `.meta`。磁盘上存在 GameEntry.ts,并不等于构建已能包含它。 ## 3. 构建二七王 Web Mobile 1. 打开 YouleNexus 的 `assets/scenes/PlatformStartup.scene`。 2. 找到 `SubgameAssets`,设置 `gameKey = erqiwang`,保留公共 `roomScene = TemplateRoom.scene`,保存场景。不要再绑定 createRoom、room;这两个 prefab 由目标入口自动加载。 3. 核对二七王 XML;版本字段与原生读取约定见[版本配置](version-and-build.md)。 4. 在项目扩展管理中启用 **Youle Version Manifest**。 5. 打开“项目 → 构建发布”,选择 **Web Mobile**,启动场景选择 **PlatformStartup**。 6. 参与构建的场景包含 PlatformStartup、PlatformLoading、PlatformLogin、PlatformLobby、TemplateRoom。TemplateRoom 是公共空白承载场景,名称包含 Template 不代表打入模板玩法。 7. 在 Bundles 取消全选,选择 `resources`、`game-erqiwang`、`version-erqiwang`。`main`、`internal` 为正常构建自动保留的公共包。排除 `game-Game_Surface_3`、`version-Game_Surface_3` 以及所有其他游戏的包。 8. 当前工程采用 debug/local 配置,保留 Debug。取消 Debug 不会自动切换生产配置,详见[开发与发布环境](version-and-build.md#6-开发构建与正式发布的区别)。 9. 使用新的独立输出目录,例如 `build/erqiwang-web-check`。在未验证跨游戏增量清理前,不把另一款游戏的旧产物目录直接用作发布目录。 10. 执行构建。构建期间不要修改启动场景、XML 和相关 Bundle 元数据。 11. 确认构建成功,且日志出现 `[youle-version-manifest] erqiwang: .../version.xml`。然后执行下文产物检查与 HTTP 运行验证。 无需更改 defaults.ts、公共注册表、框架 prefab 或引擎安装目录。 ## 4. 切换到模板或新增游戏 构建模板时,把启动场景 `gameKey` 改为 **Game_Surface_3** 并保存;保留公共场景与 `resources`,选择 `game-Game_Surface_3` 和 `version-Game_Surface_3`,排除二七王两个包,使用新的模板输出目录。 模板目录名是 template,但 gameKey 是 Game_Surface_3。不要把目录名直接当作 gameKey;游戏入口名、Bundle 名和版本资源路径必须一致。 新游戏先按[接入指南](../integration/README.md)在自己的目录中提供定义、入口、prefab 和 XML。完成后,构建步骤相同:选择 ``,保留 `game-`、`version-` 及公共包,排除所有其他游戏包。构建选择属于应用配置,不是在框架代码中增加游戏分支。 ## 5. 保存与复用构建配置 在构建面板配置好平台、场景、Bundle 和输出位置后,使用 **Export** 保存配置;以后用 **Import** 恢复。建议每款游戏保留独立的构建配置,使用时仍核对启动场景已保存的 gameKey。 下列仅展示二七王配置的 Bundle 部分,**不是完整可导入文件**;其余字段由当前 Creator 构建面板导出,不手工拼凑启动场景 UUID。 ```json { "bundleConfigs": [ {"root": "db://assets/resources", "name": "resources", "output": true}, {"root": "db://assets/games/erqiwang", "name": "game-erqiwang", "output": true}, {"root": "db://assets/games/erqiwang/resources", "name": "version-erqiwang", "output": true}, {"root": "db://assets/games/template", "name": "game-Game_Surface_3", "output": false}, {"root": "db://assets/games/template/resources", "name": "version-Game_Surface_3", "output": false} ] } ``` `root` 使用 **db:// 资源目录路径,不使用 UUID**。构建工具应在提交构建任务时提供选择结果;当前版本 XML 扩展不负责修改 Bundle 勾选项,也不保证发现所有代码或资源泄漏。 当前 `npm run build-game` 对应旧的独立子工程实体化脚本,不是上述同工程 Bundle 构建的一键入口。参见[历史脚手架说明](legacy-project-layout.md)。 ## 6. 检查实际产物 二七王构建的关键目录应为: ```text <输出目录>/ index.html version.xml assets/ internal/ main/ resources/ game-erqiwang/ version-erqiwang/ src/ settings.json ``` 还会有引擎代码、样式等公共文件。检查以下内容: - `assets` 不存在 game-Game_Surface_3、version-Game_Surface_3 或其他未选游戏目录。 - `src/settings.json` 的 assets.projectBundles 只列出当前公共包与二七王两个包;数组顺序不是验收条件。 - 检查所有生成 JS,不能出现 createTemplateGame、TemplateCreateRoomView、TemplateRoomView、GameEntry_Game_Surface_3 等模板实现。仅删除 Bundle 文件夹不能清除已混入公共脚本的代码。 - 版本包的资源路径包含 `erqiwang/version`,不能只检查版本包文件夹是否存在。 - 输出根目录 version.xml 与源 XML 字节或 SHA256 一致。保持原生兼容文件名,不改成 gameKey.xml。 在 cocoscreator_projects 目录使用 PowerShell 检查某次输出,按实际目录修改第一行: ```powershell $webOutput = Resolve-Path 'YouleNexus/build/erqiwang-web-check' Get-ChildItem (Join-Path $webOutput 'assets') -Directory | Select-Object -ExpandProperty Name $settings = Get-Content (Join-Path $webOutput 'src/settings.json') -Raw | ConvertFrom-Json $settings.assets.projectBundles Get-FileHash 'YouleNexus/assets/games/erqiwang/resources/erqiwang/version.xml' Get-FileHash (Join-Path $webOutput 'version.xml') rg -n 'createTemplateGame|TemplateCreateRoomView|TemplateRoomView|GameEntry_Game_Surface_3' $webOutput -g '*.js' ``` 最后一条没有匹配时,rg 返回码为 1,表示未检出这些标记。标记扫描只是辅助检查,不代替依赖边界和实际运行验证。 ## 7. 运行与回归验证 通过 HTTP 服务或 Creator 构建预览打开导出目录,不用 file:// 双击 index.html。查看浏览器 Network 和控制台: 1. 只请求公共包、game-erqiwang、version-erqiwang,没有未选游戏包请求或 404。 2. 进入登录页,版本来自目标 XML,启动没有 terminal/fatal 错误。 3. 成功登录后,验证创建页与房间视图是二七王;验证创建房间、服务器拒绝和重连等真实业务路径。这一步需要测试账号与运行中的服务器,本次解耦验证没有代替完整牌局回归。 源码检查从 cocoscreator_projects 运行: ```powershell node scripts/check-import-boundaries.mjs node scripts/check-room-assets.mjs node --experimental-transform-types --test framework-tests/architecture/subgame-entry.test.ts node --test scripts/test/version-manifest-build.test.mjs node node_modules/typescript/bin/tsc -p tsconfig.framework.json --noEmit ``` 类型和源码测试通过不等于产物通过;正式发布以本次实际生成的目录和运行结果为准。 ## 8. 常见故障 - **Missing subgame entry**:核对 gameKey、入口 ccclass 名、游戏包勾选及 GameEntry.ts 的编辑器导入状态。不要添加模板回退入口。 - **Load assets/game-.../index.js failed**:检查目标游戏包是否进入构建、部署路径是否完整;若只在编辑器场景进程发生,用浏览器预览或导出包确认,不能直接当成浏览器运行结果。 - **Bundle version-... doesn't contain .../version**:检查嵌套包优先级,确认 XML 实际归属版本包,而非父游戏包。 - **本地配置读取失败,dev-config 路径不能解析**:检查公共 resources 是否被排除,同时核对当前是否采用 debug/local 配置。 - **旧游戏仍进入产物**:检查 Bundle 是否全选、公共代码是否静态导入游戏、公共 prefab/场景是否引用私有游戏脚本或资源,以及输出目录是否来自旧构建。 - **切换 gameKey 后仍请求旧游戏**:保存真正用于构建的启动场景,重新构建;检查浏览器缓存或部署缓存,不能只改编辑器中未保存的 Inspector。 - **输出缺少根 version.xml**:确认项目扩展启用并完成构建,查看具体扩展错误。扩展失败的产物不要通过手动补文件冒充成功。