Files
AIGame/Doc/WeChat_Export.md

140 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 微信小游戏导出、导入与首包 CDN
## 开发者工具入口
导出菜单为 `AIGame/WeChat/Export Base Package`,输出到 `AIClient/Build/WeChat/Base/`。
- `minigame/` 是开发者工具项目,包含 `game.js`、`game.json`。
- `webgl/` 是网站资源目录。打开它或父目录时若没有正确配置源码路径,会出现找不到 `game.json`。
- 导出后现在同时生成父目录 `project.config.json`,指定 `miniprogramRoot: "minigame/"`;因此可以打开 Base 或 minigame。
- 父目录入口沿用 SDK 编译配置及符号文件排除规则,保留已有 AppID;不改私有配置。
- `AIGame/WeChat/Open Exported MiniGame Folder` 定位正确的项目目录;旧包可以执行 `Repair Exported DevTools Project`。
## 启动资源下载 404
当前首包 CDN 为 `https://www.xworld.ren/game/Friends/webgl/`,与生产热更新目录位于同一个网站目录。
导出菜单会通过 Unity API 写入 MiniGameConfig 的 CDN,并由 SDK 写入 `minigame/game.js` 的 `DATA_CDN`。
修改现有包配置可用 `AIGame/WeChat/Refresh Exported Config (No Build)`,无需重新编译 Player。
**导出只生成本地文件,不会自动上传网站;重新生成底包不等于必须重新上传全部资源。** 首次部署或缺少文件时,将 `AIClient/Build/WeChat/Base/webgl/` 中需要的资源上传到网站 `/game/Friends/webgl/`,保持相对路径,不要额外嵌套一层 webgl。
| 本地相对 webgl 的路径 | 对外 URL 路径 |
| --- | --- |
| `<hash>.webgl.data.unityweb.bin.txt` | `/game/Friends/webgl/<hash>.webgl.data.unityweb.bin.txt` |
| `StreamingAssets/cdn/version.json` | `/game/Friends/webgl/StreamingAssets/cdn/version.json` |
| `StreamingAssets/yoo/...` | `/game/Friends/webgl/StreamingAssets/yoo/...` |
`base-package-report.txt` 会列出本次实际首包文件和完整下载地址。
2026-10-22 的包为 `1ddb5fcad4415dd3.webgl.data.unityweb.bin.txt`,10,084,442 字节;排查时对应生产 URL 返回 404,而现有 `/game/Friends/webgl/cdn/version.json` 返回 200。
SDK 根据 Unity data 文件内容计算哈希,并写入文件名和 `game.js` 的 `DATA_FILE_MD5`。重新构建后,如果哈希未变且现有 CDN 的完整 URL 可访问,直接复用,无需重复上传;哈希变化时才需要补充对应的新文件。未变的 YooAsset 业务资源包同样无需重复上传。场景或壳内资源/构建设置变化可能影响 Unity data,不能仅凭业务资源未修改就判断其哈希一定不变。
排查 404 时,先核对 `DATA_CDN` 与既有文件部署位置,再核对 `DATA_FILE_MD5` 对应的文件是否存在。404 本身不能证明资源内容发生了变化。修正路径或补齐缺失文件后,确认完整 URL 返回 200,再清理开发者工具缓存并编译。
Unity 首包的 `DATA_CDN` 与游戏进入 Boot 后使用的 YooAsset `version.json`/Art/DefaultPackage 是两阶段下载。当前 YooAsset 生产清单地址仍为 `/game/Friends/webgl/cdn/version.json`,资源根为 `/game/Friends/webgl/yoo/DefaultPackage`。
## 验证
`AIClient/AgentScripts/VerifyWeChatExport.cs` 通过 Unity Pipeline 刷新并验证现有包配置,检查父目录入口、AppID、SDK 排除规则、私有配置与 webgl 资源保留、重复刷新幂等性。
回执及修改前备份在 `Tools/output/wechat_export/`。本次本地验证通过,服务器首包文件尚需发布。
## YooAsset 默认构造函数被裁剪
2026-10-22 小游戏启动出现 `MissingMethodException: Default constructor not found for type YooAsset.WebNetworkFileSystem`。
YooAsset 3.0.6 的 `FileSystemParameters.CreateFileSystem` 使用 `Type.GetType` 和 `Activator.CreateInstance` 创建实例。
实际检查完整与 WebGL ManagedStripped 程序集,确认 WebNetwork/Builtin/Sandbox 三种文件系统在完整程序集中有默认构造函数,裁剪后类型仍存在、默认构造函数已移除。
`AIClient/Assets/AOT/link.xml` 仅保留项目使用的这三个文件系统的无参构造函数,不全量保留 YooAsset,也不降低全局裁剪级别。
该文件独立于 `Assets/HybridCLRGenerate/link.xml`,后续 HybridCLR Gen All 不会覆盖它。Unity 保留规则见[官方托管代码裁剪说明](https://docs.unity3d.com/cn/2022.3/Manual/ManagedCodeStripping.html)。
`AIClient/AgentScripts/VerifyYooAssetStripping.cs`:`Before` 记录裁剪前后构造函数;`BuildAndVerify` 执行正式 Export Base Package,检查新裁剪 DLL 中的构造函数及方法体、新生成的原生构造函数,并对比业务 bundle 与启动 data 的内容哈希。
回执目录为 `Tools/output/yooasset_stripping/`。底包构造函数修复需要新的 wasm 代码生效;未改动的业务资源包继续复用。
本次 20:06 正式导出与产物检查通过:三种文件系统无参构造函数及方法体均已保留,IL2CPP 已生成 WebNetworkFileSystem 构造函数;业务 bundle 内容哈希全部未变。启动 data 实测由 10,084,442 字节变为 10,084,535 字节,文件名变为 `c58ae17711192f12.webgl.data.unityweb.bin.txt`;需要将这个新增启动文件同步到现有 `/game/Friends/webgl/`,无需重传未变业务 bundle。未自动发布服务器,微信开发者工具运行尚待复测。
## 主界面移动端修复产物(2026-10-22 20:49)
启动不再自动加载 测试场景/CaoCao。主界面角色预览材质通过 Prefab 依赖进入 Art,顶部和底部布局使用设备/微信安全区,详见 `UI_AutoGen_Overview.md`。
三个屏幕布局与按钮命中、GPU 抠底、实际启动器无 3D 预加载检查通过;8 组微信窗口/胶囊/旧接口/DPR 用例通过。原 Boot 场景已恢复。
新底包已导出到 `AIClient/Build/WeChat/Base/minigame/`,构建成功并确认原生/JS 安全区桥接均包含。新首包为 `e33b1380f2e627d5.webgl.data.unityweb.bin.txt`(14,785,194 字节)。本次业务 UI 和热更代码有实际修改,需部署对应 Art/DefaultPackage 更新;相对上一构建仅 3 个 Art bundle、1 个热更 rawfile 及相应清单变化。
`Tools/output/home_mobile/deployment.json` 列出需发布文件、本地路径与目标 URL(排除构建报告和日志),资源文件先于总版本清单发布。该适配包含新的 AOT 组件,应搭配新底包。文件目前只在本地构建/暂存,未上传 CDN,微信开发者工具/真机需重新编译复测。
## 2026-10-22:小游戏网络与启动遮罩修复
- `WsClient` 原 WebGL 分支只有“不支持 ClientWebSocket”的占位。现在通过 `Assets/AOT/Scripts/Boot/WebSocketBridge.cs` 与 `Assets/Plugins/WebGL/GameWebSocket.jslib` 使用微信 `wx.connectSocket` / `SocketTask`;普通浏览器回退到 WebSocket。轮询收发在 Unity 主线程处理,包含连接超时、指数退避、手动重连和关闭清理。AOT 原生导入独立保留,避免热更 DLL 直接声明 P/Invoke。
- WebGL 的 `GameNet.Bind` 对本机或非 HTTPS/WSS 地址回退为 `https://game.xworld.ren` 和 `wss://game.xworld.ren/ws?pid={pid}&token={token}`,同时更新 BootContext,供业务 HTTP 使用。编辑器本机配置保留;自定义 HTTPS/WSS 远端地址保留。
- 截图中首次 `/login` 返回 401 后出现 `authed pid=...`,对应游客首次登录失败后自动注册成功,并非最终鉴权失败。ASTC 不支持后软件解压属于纹理兼容提示,与 WebSocket 占位错误不同。
- 原 Boot 固定两帧就隐藏遮罩,异步加载主界面时会暴露空白。现在等待热更通过 BootContext 通知主界面就绪;缺少 HUD 或超时保留可见错误提示,该信号不依赖登录或 WebSocket 成功。
- 验证:`node Tools/verify_game_websocket.js` 的 8 组实际 JS 桥接用例;`dotnet run --project Tools/Tests/WebSocket/WebSocket.csproj` 编译并执行实际 UNITY_WEBGL WsClient;Pipeline 的 `VerifyMiniGameNetwork.Endpoints` / `CheckUiReady` 与 `VerifyHomeMobileUi.CheckReady`。隔离场景验证完成后恢复原 Boot 场景。
- 新增 AOT / JS 桥接与上下文,必须搭配新底包和本次 DefaultPackage 热更,不能只刷新导出配置或只替换旧底包的热更 DLL。Art 未修改,无需重新构建或重复上传未变的 Art bundles。构建与发布清单见 `Tools/output/minigame_network/`;本地构建不自动上传 CDN。微信后台需配置 request 合法域名 `https://game.xworld.ren`、socket 合法域名 `wss://game.xworld.ren`。开发者工具和真机仍需运行复测。
本轮最终本地构建已成功(约 232 秒),底包目录 `AIClient/Build/WeChat/Base/minigame/`。首包数据 `06add2285b23eace.webgl.data.unityweb.bin.txt`(14,785,694 字节);DefaultPackage 清单 `0e3722bbb19457d47bac35bbd4b516a7`,热更文件 `d34a46086ecefa40084479f551820a4e.rawfile`(253,440 字节)。Art 仍为 `006c201e92439eb03ae12d84b86f8fa6`,未变。已验证 4 个平台桥接原生导入、IL2CPP 返回字符串释放、生成 framework 中的桥接、Raw DLL 内容和清单 MD5;原 Boot 场景恢复,编辑器停止且编译完成。`Tools/output/minigame_network/deployment.json` 给出逐文件来源/URL,先发布资源文件,再发布总版本清单;未上传远端,未做微信真机联调。
后续线上核对:新首包 `06add2285b23eace.webgl.data.unityweb.bin.txt` 已返回 200;但 `/cdn/version.json` 仍下发旧热更版本 `5d00808a861cf2d9d5696eaafea5b896`,新 DefaultPackage 清单返回 404,导致新壳继续运行旧 DLL。已将本次缺少的 4 个 DefaultPackage 文件和 `cdn/version.json` 按网站路径整理到 `Tools/output/minigame_network/upload_patch/`,共 254,085 字节。将目录内容上传到网站 `/game/Friends/webgl/`,先 `yoo/DefaultPackage`,最后 `cdn/version.json`;首包与 Art 无需重复上传。仅本地整理,未执行上传。
## 2026-10-22:玩法 API 404 与预览紫色区域
线上新热更已生效,WebSocket 和主界面加载正常;`https://game.xworld.ren/game/state` 仍返回 404,且响应为 Kestrel。本仓库的完整玩法服务为 AIServer,Windows Server 上传/启动方式见 `AIServer/deploy/windows/README.md`。本地已生成并验证 `Tools/output/server_release/AIServer-Windows-x64.zip`,不含开发数据库,不自动替换旧服务;全部游戏域名路由需切到同一新后端,旧后端数据需要单独迁移。
实际 Art 材质仍保存旧抠底色 (0.07,0.02,0.09),而热更代码改为紫色清屏,导致矩形显现;现已改为读取运行时材质 `_Key`。旧/新颜色的 GPU discard 与前景保留、隔离预览截图通过。客户端修复仅更新热更代码,无需底包/Art 重打:上传 `Tools/output/server_release/Client-CDN-Patch.zip` 解压内容到 `/game/Friends/webgl/`,先 `yoo/DefaultPackage`,最后 `cdn/version.json`。新 packVersion `587e28dfd1f166d117eadd24afa8efa1`,仍搭配既有支持 WebSocket 的新底包。两个 ZIP 均未上传线上。
## BuddyDefense 15888 部署地址(当前)
游戏服务已改为 `https://BuddyDefense.xworld.ren:15888` / `wss://BuddyDefense.xworld.ren:15888/ws?pid={pid}&token={token}`,CDN 资源路径维持既有部署。本轮 packVersion `d36750d301123c62fd6f673f324137a5`,发布文件 `Tools/output/server_release/Client-BuddyDefense-15888.zip`,仍先发布 yoo/DefaultPackage、最后发布 cdn/version.json。新常量会在编译时内联进热更 DLL,不增加运行时 AOT API 依赖;既有支持 WebSocket 的底包可直接更新热更,无需重打。
服务器包 `AIServer-BuddyDefense-15888.zip` 默认监听 `127.0.0.1:15888`。用户现有 Caddy 站点也监听 15888,需要加 `bind` 绑定服务器实际非环回网卡 IPv4,避免通配监听占用环回端口;`New-CaddySite.ps1` 在服务器运行可生成准确片段,保留 transport http 的 read_timeout/write_timeout 0。云服务器存在公网 NAT 时使用网卡私网地址绑定,域名 DNS 指向公网地址。更新已运行任务时先使用 Stop-Server.ps1,再安装新开机任务;更改 Caddy 后验证并 reload。需配置新域名的 DNS、证书及公网 TCP 15888 放行。当前本地验证正常,未部署远端。
客户端 ZIP 的网站发布辅助:将 `Publish-BuddyDefenseClient.ps1` 与 `Client-BuddyDefense-15888.zip` 放在同一目录,管理员 PowerShell 执行 `powershell.exe -ExecutionPolicy Bypass -File .\Publish-BuddyDefenseClient.ps1 -WebglRoot "网站中/game/Friends/webgl/对应的实际目录"`。也可先加 `-WhatIf` 检查。脚本校验清单 MD5,最后发布总版本;该目录属于静态资源站点,不是 AIServer 程序目录。发布后通过公网 `https://www.xworld.ren/game/Friends/webgl/cdn/version.json` 确认 packVersion 为 `d36750d301123c62fd6f673f324137a5`。新游戏域名的 DNS/TLS/15888 入口须先可访问。
### 2026-10-23 任务面板打开异常
TMP 会在多段文字下生成同名的 TMP_SubMeshUI 字体渲染子节点;PrototypeFlow.Panel 原先索引全部 Transform 时抛出重复键异常。现按组件排除内部渲染节点,保留业务节点绑定与重名校验。19 个业务面板(含任务、签到、背包、好友)预览场景验证通过。
本次仅发布 DefaultPackage 热更:packVersion `613942741fd3be253c86145d7451031c`,Art 保持 `006c201e92439eb03ae12d84b86f8fa6`。将最新 `Tools/output/server_release/Client-BuddyDefense-15888.zip` 放到服务器发布脚本旁,继续使用 `Publish-BuddyDefenseClient.ps1 -WebglRoot "C:\XWorld\CDN\Friends\webgl"`,脚本先写资源后更新 cdn/version.json。无需重打底包。未由 Agent 上传线上,发布后重新进入小游戏验证点击任务。
## SSH 一键发布 CDN(2026-11-04)
已接通服务器 `Administrator@159.75.128.109:22`,网站目录 `C:\XWorld\CDN\Friends\webgl`。当前发布使用 `Tools/publish_cdn.py` 与服务器端执行的 `Tools/Publish-CdnRelease.ps1`;旧 `Tools/cdn_publish.py upload` 使用旧通道布局,不用于当前网站发布。
Unity 菜单位于 **AIGame/CDN**:
- `Check SSH Connection`:检查免密连接与目标目录。
- `Preview Upload Changes`:只读比较服务器与本地暂存文件,记录需上传的差异。
- `Upload Staged Resources`:发布已构建的资源。
- `Build And Upload (Art + HotUpdate)`:依次检查连接、构建当前 WebGL Art/热更新包并发布,不构建 Player。要求编辑器为 WebGL 目标且不在 Play Mode。
- `Prepare SSH Key`:首次生成专用密钥及服务器公钥安装脚本。
- `Open Publish Folder`:查看预览、日志、ZIP 与发布回执。
本机配置位于 `Tools/cdn_publish.local.json`,示例为 `Tools/cdn_publish.example.json`。专用密钥位于 `Tools/.cdn-deploy/`,两个本机路径均已加入 Git 忽略规则。Windows 私钥 ACL 限制为创建者与 SYSTEM;服务器 Administrator 默认公钥文件为 `C:\ProgramData\ssh\administrators_authorized_keys`。SSH 使用 BatchMode 与严格主机密钥检查,不处理账号密码;公钥安装脚本仅包含公钥。更换网络出口时需更新云防火墙来源白名单。公钥配置依据:https://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement 。
命令行(仓库根目录):
```powershell
python Tools/publish_cdn.py check
python Tools/publish_cdn.py plan --compare
python Tools/publish_cdn.py upload
python Tools/publish_cdn.py upload --startup-export AIClient/Build/WeChat/Base
python Tools/publish_cdn.py rollback --release <发布回执中的32位releaseId>
```
发布从 `Tools/cdn_root/wechat/version.prod.json` 读取包版本;验证清单 MD5、YooAsset CRC、版本标记并计算每个文件 SHA256。服务器比较后仅传输差异 ZIP,验证包含未变服务器文件的完整发布集合,防止遗漏文件。服务器先写资源,最后原子替换 `cdn/version.json`;发布时检查原版本未被其他发布者更改。保留旧资源与服务器私有目录中的上一版版本清单,回滚拒绝覆盖后续不同版本。服务器发布后从公网重新读取总版本与包清单进行校验;如果公网检查失败,会明确报告“服务器已发布”,不自动重复提交。
`--startup-export` 是新底包构建后的可选步骤:从该导出目录的 `minigame/game.js` 精确选择当前启动 data,校验 DATA_CDN、DATA_FILE_SIZE 和 SDK 使用的 MD5 中间 16 位命名,仅将对应的 `.webgl.data.unityweb.bin.txt` 加入同一发布事务。服务器路径白名单不允许任意根目录文件;公网额外验证启动 data 的完整 SHA256。原底包和旧哈希资源保留,回滚只切换远端热更版本,不会切换本地微信底包。Unity 常规资源发布菜单仍不自动构建 Player 或附带首包。
本轮实际发布:`releaseId=05a167475cd6402291421c746379c7c4`;DefaultPackage `d0116d388c58c3c73593c02037d0e3ad`,Art `0fd7811b1c0988f4b728dadb59041f38`。306 个本地文件共 69.48 MiB,实际差异 27 个文件/12.70 MiB,包括 HomeCamp +0.30 EV 曝光与首页接入。服务器完整性验证及公网两份清单 MD5 通过。回执:`Tools/output/cdn_publish/release-05a167475cd6402291421c746379c7c4.json`。11 项本地发布事务测试通过,覆盖损坏/缺失上传、过期版本、路径穿越、无变更、旧资源保留与回滚。
此流程发布 Art 和热更新资源;如变更 AOT/JS 桥接或底包配置,仍需按微信导出流程生成并部署相应底包及启动数据。
### HomeCamp 热更新兼容旧底包(2026-11-04)
微信开发者工具实际 Boot 日志已读取新版 `d0116d388c58c3c73593c02037d0e3ad`,但首页仍显示旧插画,原因是 `MissingMethodException: MethodNotFind YooAsset.SceneHandle::add_Completed`。10 月 22 日导出的 WebGL 底包裁剪了 `SceneHandle.Completed` 和 `UnloadSceneAsync`,因此不是 CDN 未上传或客户端未读取新版本。
`MainHudView.cs` 中的 HomeCampPresenter 改为在常驻 UiManager 上以协程轮询旧底包保留的句柄状态,卸载改用 Unity SceneManager(YooAsset 通过 sceneUnloaded 回收句柄)。下载期间隐藏或销毁首页仍能完成清理。无需重打底包。
`AIClient/AgentScripts/InspectHomeCampAot.cs` 通过 Pipeline 检查旧 ManagedStripped 与实际生成的热更 DLL,确认 SceneHandle/HandleBase 引用均存在;回执 `Tools/output/homecamp_aot_compatibility/aot_check.json`。兼容修复仅上传 5 个差异文件/0.25 MiB,Art 不变;新 DefaultPackage `5b9d783853bd29484ecf828fbf33af47`,发布回执 `Tools/output/cdn_publish/release-4fdfb222706a47879f1511dd532630cf.json`,服务器及公网清单验证通过。
微信开发者工具使用现有底包普通重新编译后,Boot 确认加载上述新版本;首次下载完成后显示降低曝光后的 3D HomeCamp,商店打开后返回营地正常,本轮无红色异常。开发者工具仍有 ASTC 软件解压和加载帧耗时提示;未进行微信真机性能验收。
### 启动画面整理(2026-11-04,待构建新底包)
用户截图的第一段深棕底花屏对应 Unity Splash Logo:项目开启 show/showUnityLogo,底色为 `#231F20`,当前许可支持关闭。第二段来自旧 `BootPatchView.Create()` 运行时拼装的黑底 AIGame/方形进度条;LegacyRuntime 字体无法正常显示所用中文。这两段属于启动壳,不是远端 HomeCamp 资源。
本地已通过 Pipeline 关闭 Splash,并将启动界面改为 `Doc/UIPrefabCreater/UI_BootLoading.json` → `Assets/AOT/UI/UI_BootLoading.prefab`。它在初始化 YooAsset 前就要显示,因此随 Boot 场景直接引用并放在 AOT 目录,不进入业务 Art 加载链路。复用已有营地插画与 Common 九宫格,使用独立静态中文子集 `Assets/AOT/UI/BootChinese.asset`,保留插画比例并裁切铺满。状态仅展示易懂的加载提示;版本哈希留在日志,进度单调平滑增长,营地准备好后才到 100% 并淡出。
`GameplayBootstrap` 将 MainUiReady 推迟到 HomeCamp 结束加载后,避免先展示旧插画 HUD 再切换 3D。`AIGame/Boot/Build Loading Screen` 可重建字体/Prefab/Boot 引用;导出基础包会检查配置,Setup Boot Scene 也保留启动 Prefab 引用。JsonUIPrefabBuilder 的 TMP 组件新增可选 `fontAsset` 明确路径,既有 JSON 默认字体行为不变。
验证入口 `AIClient/AgentScripts/VerifyStartupPresentation.cs`;1080×1920 与 1080×2338 两组实际 Prefab 预览通过中文字符覆盖、文本溢出、铺满且不拉伸、进度不回退与完成淡出检查,原场景和 Game View 已恢复。截图及回执位于 `Tools/output/startup_presentation/`。本轮尚未构建 Player、替换小游戏底包或发布 CDN;需经明确授权后构建新底包、同步新的启动 data 并在微信端复测,旧壳不能仅靠热更替换启动画面。