minigame-tuanjie-transform-sdk/Editor/PCHighPerformance/README.md
2026-04-07 19:54:56 +08:00

287 lines
10 KiB
Markdown
Raw 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.

# PC 高性能小游戏开发指南
## 目录
- [架构概览](#架构概览)
- [两条接入路径](#两条接入路径)
- [文件结构](#文件结构)
- [宏开关机制](#宏开关机制)
- [初始化机制](#初始化机制)
- [构建流程](#构建流程)
- [通信协议](#通信协议)
- [问题排查](#问题排查)
- [调试工具](#调试工具)
- [更新日志](#更新日志)
---
## 架构概览
```
C# (Unity) ←→ direct_applet_sdk.dll ←→ 微信内核 ←→ 基础库
```
| 模块 | 职责 |
|------|------|
| `WXPCHPInitScript` | MonoBehaviour运行时核心——DLL P/Invoke、消息收发、回调调度 |
| `WXPCHighPerformanceManager` | 门面类,提供类似 `wx.xxx()` 的上层 API |
| `PCHPBuildPreProcessor` | 构建预处理器,自动管理宏定义和场景注入(兜底) |
| `WXPCHPBuildHelper` | 路径A 构建配置助手(转换工具链集成) |
| `WXPCHPWindow` | Editor 窗口 UI + 宏开关菜单 |
| `WXPCSettingHelper` | 路径B 构建设置管理(独立窗口) |
| `WXApkgPacker` | wxapkg 打包工具 |
---
## 两条接入路径
```
路径 A: "转换工具链" ← 走 WX-WASM-SDK 转换面板,项目本身是小游戏工程
路径 B: "原生接入" ← 项目本身就是 Standalone只想接 PC 高性能能力
```
| 维度 | 路径 A转换工具链 | 路径 B原生接入 |
|------|---------------------|-------------------|
| **宏定义** | 转换工具/PreProcessor 自动添加 `WX_PCHP_ENABLED` | 开发者通过菜单一键开启,或手动添加 |
| **Build Target** | WebGL/WeixinMiniGame → 临时切 Standalone → 切回 | 始终 Standalone不切换 |
| **初始化方式** | `RuntimeInitializeOnLoadMethod` 自动 + PreProcessor 兜底注入 | `RuntimeInitializeOnLoadMethod` 自动,或开发者手动挂载 |
| **Editor 入口** | "微信小游戏 → 生成并转换" 面板 | "微信小游戏 → 转换PC高性能模式" 独立窗口 |
| **构建后** | `RestoreToMiniGamePlatform()` 恢复平台 | 不恢复,保持 Standalone |
| **多平台兼容** | `WX_PCHP_ENABLED` 不在 WebGL 下定义,无干扰 | `WX_PCHP_ENABLED` 只在 Standalone 下定义Android/iOS 不受影响 |
---
## 文件结构
```
WX-WASM-SDK-V2/
├── Editor/PCHighPerformance/
│ ├── PCHPBuildPreProcessor.cs # 构建预处理器(宏管理 + 兜底注入)
│ ├── WXPCHPBuildHelper.cs # 路径A 构建配置助手
│ ├── WXPCHPWindow.cs # 编辑器窗口 + WX_PCHP_ENABLED 宏开关菜单
│ ├── WXPCSettingHelper.cs # 路径B 构建设置管理
│ └── WXApkgPacker.cs # wxapkg 打包
└── Runtime/
└── WXPCHPInitScript.cs # SDK 运行时脚本(整文件 #if WX_PCHP_ENABLED
```
---
## 宏开关机制
### `WX_PCHP_ENABLED` — 总开关
**作用**:控制 `WXPCHPInitScript.cs``WXPCHighPerformanceManager` 是否参与编译。
**未定义时**Runtime 脚本整文件跳过编译Android/iOS/WebGL 等平台完全无干扰。
**定义方式**(三选一):
| 方式 | 适用场景 |
|------|---------|
| Editor 菜单:`微信小游戏 → PC高性能模式宏开关` | 路径B一键切换 |
| `PCHPBuildPreProcessor` 自动添加 | 路径A/BStandalone 构建时自动 |
| 手动:`Player Settings → Scripting Define Symbols` 添加 `WX_PCHP_ENABLED` | 任何路径 |
### `UNITY_STANDALONE_WIN` — 平台细分
`user32.dll``GetActiveWindow`、`MessageBox`)的 P/Invoke 声明被 `#if UNITY_STANDALONE_WIN` 包裹macOS 构建时不会引入。
---
## 初始化机制
### 三级策略(优先级从高到低)
| 优先级 | 方式 | 说明 |
|--------|------|------|
| 1 | **开发者手动挂载** | 场景中已存在 `WXPCHPInitScript` 组件 → `AutoInitialize` 检测到 `Instance != null`,跳过 |
| 2 | **`RuntimeInitializeOnLoadMethod`** | 场景加载后自动创建 GameObject 并挂载,零侵入不修改任何场景文件 |
| 3 | **构建时注入(兜底)** | `PCHPBuildPreProcessor` 在路径A 转换工具链模式下注入首场景 |
### 运行时初始化流程
`WXPCHPInitScript.Initialize()``Awake` 时触发5 步串行:
```
InitEmbeddedGameSDK() → 加载 DLL初始化底层 SDK
RegisterAsyncMsgHandler() → 注册 C# 静态回调到 DLL防 GC 回收)
EstablishConnection() → 建立 Mojo IPC 连接
GetActiveWindow() → Windows: 获取 HWND / macOS: IntPtr.ZeroDLL 内部处理)
InitGameWindow(hwnd) → 把窗口句柄传给内核,绑定渲染窗口
```
任何一步失败整个链路中断Windows 平台会弹 `MessageBox` 提示具体步骤。
---
## 构建流程
### PCHPBuildPreProcessor构建预处理器
**触发条件**:任何 Standalone (Windows/macOS) 构建
**流程**
```
构建开始
① 确保 WX_PCHP_ENABLED 宏已添加到 Standalone ScriptingDefineSymbols
② 检查 WXPCHPInitScript 类型是否存在
├─ 未找到 → 跳过(可能需要宏生效后重新编译)
└─ 找到 → 继续
③ 检查首场景是否已有 WXPCHPInitScript 组件
├─ 已有 → 跳过注入(开发者手动挂载的)
└─ 没有 → 检查是否为转换工具链模式
├─ 是 → 兜底注入到首场景
└─ 否 → 依赖 RuntimeInitializeOnLoadMethod 自动初始化
```
### 路径A — 转换工具链构建WXPCHPBuildHelper
`WXConvertCore` 在小游戏构建完成后调用,额外步骤:
- 构建产物打包为 wxapkg 格式
- 构建完成后调用 `RestoreToMiniGamePlatform()` 恢复到 WebGL/WeixinMiniGame
### 路径B — 独立窗口构建WXPCSettingHelper
通过 `微信小游戏 → 转换PC高性能模式` 菜单打开,特点:
- 自动确保 `WX_PCHP_ENABLED` 宏已定义
- 不强制注入场景(依赖 `RuntimeInitializeOnLoadMethod`
- 构建完成后 **不恢复平台**,保持 Standalone
---
## 通信协议
### 消息方向
| type | 方向 | 用途 |
|------|------|------|
| `"request"` | C# → 内核 | 调用 wx APIshowToast、login 等) |
| `"event_register"` | C# → 内核 | 订阅事件onShow、onHide 等) |
| `"event_unregister"` | C# → 内核 | 取消事件订阅 |
| `"response"` | 内核 → C# | API 回调success / fail / complete |
| `"event"` | 内核 → C# | 事件推送 |
### 线程模型
DLL 回调在非主线程,通过 `ConcurrentQueue` 转到主线程 `Update` 中处理:
```
DLL 线程: HandleAsyncMessage → 反序列化 → _messageQueue.Enqueue()
主线程: Update → ProcessMessageQueue → ProcessResponse → 触发回调
```
---
## 问题排查
### 快速检查清单
- [ ] `Player Settings → Scripting Define Symbols` 包含 `WX_PCHP_ENABLED`
- [ ] Build Settings 中有至少一个启用的场景
- [ ] 导出目录包含 `.exe``direct_applet_sdk.dll`(同级)
- [ ] 运行 .exe 后 Player.log 有 `[WXPCHPInitScript]` 日志
### 问题 1Android/iOS 构建时报 DLL 相关编译错误
**原因**`WX_PCHP_ENABLED` 宏被错误添加到了非 Standalone 平台
**解决**:在 `Player Settings → Scripting Define Symbols` 中,确保只有 Standalone 平台定义了 `WX_PCHP_ENABLED`。或通过菜单 `微信小游戏 → PC高性能模式宏开关` 关闭。
### 问题 2DLL 加载失败(~90% 的运行时问题)
**症状**:运行 .exe 后没有弹窗,日志报 `DllNotFoundException`
**验证导出目录结构**
```
导出路径/
├── YourGame.exe
├── direct_applet_sdk.dll ← 必须存在
└── YourGame_Data/
```
**解决**:确保 `direct_applet_sdk.dll``.exe` 同级
### 问题 3GetActiveWindow 返回空句柄
**原因**:窗口尚未创建时调用了初始化
**解决**:检查 Unity Player Settings确保非后台启动或考虑延迟初始化
**注意**macOS 平台会传 `IntPtr.Zero`,由 DLL 内部获取窗口句柄,这是正常行为。
### 问题 4宏添加后代码未生效
**原因**:修改 `ScriptingDefineSymbols` 后需要 Unity 重新编译脚本
**解决**:等待 Unity 编译完成(底部进度条),或手动 `Assets → Reimport All`
### 错误代码速查
| 错误信息 | 原因 | 解决 |
|----------|------|------|
| `DllNotFoundException` | DLL 不在 .exe 同级目录 | 复制 DLL 到 .exe 目录 |
| `EntryPointNotFoundException` | DLL 版本不匹配 | 更新 `direct_applet_sdk.dll` |
| `找不到 WXPCHPInitScript 类型` | SDK 未安装或宏未生效 | 重新导入 SDK 或等待编译 |
| `GetActiveWindow 返回空句柄` | 窗口未创建(仅 Windows | 延迟初始化或检查 Player Settings |
| `WXPCHPInitScript 必须在 Runtime 程序集` | 脚本放在了 Editor 目录 | 移到 Runtime 目录 |
---
## 调试工具
### 日志查看
**Player.log 位置**
- Windows: `%APPDATA%\..\LocalLow\<CompanyName>\<ProductName>\Player.log`
- macOS: `~/Library/Logs/<CompanyName>/<ProductName>/Player.log`
**搜索关键字**`[WXPCHPInitScript]`、`DllNotFoundException`、`InitEmbeddedGameSDK`
**正常日志示例**
```
[WXPCHPInitScript] 通过 RuntimeInitializeOnLoadMethod 自动创建
[WXPCHPInitScript] ========== Awake 被调用 ==========
[WXPCHPInitScript] ========== 开始初始化 ==========
[WXPCHPInitScript] Step 1: 调用 InitEmbeddedGameSDK
...
[WXPCHPInitScript] ========== 初始化完成 ==========
```
### Editor 菜单
| 菜单项 | 功能 |
|--------|------|
| 微信小游戏 → 转换PC高性能模式 | 打开路径B独立构建窗口 |
| 微信小游戏 → PC高性能模式宏开关 | 一键启用/禁用 `WX_PCHP_ENABLED` 宏 |
---
## 更新日志
### v2.0.0 (2026-04-07)
- **双路径架构**:支持"转换工具链"和"原生接入"两条路径
- **`WX_PCHP_ENABLED` 宏**总开关整文件条件编译Android/iOS 零干扰
- **`RuntimeInitializeOnLoadMethod`**:零侵入自动初始化,不再强制修改场景
- **`user32.dll` 平台隔离**`#if UNITY_STANDALONE_WIN` 包裹macOS 兼容
- **`RestoreToMiniGamePlatform` 解耦**:从 `BuildPCHighPerformance` 的 finally 移到调用方
- **Editor 宏开关菜单**`微信小游戏 → PC高性能模式宏开关`
### v1.1.0 (2026-03-02)
- 重命名 `EmbeddedAppletSDK``WXPCHPInitScript`
- 迁移脚本到 Runtime 目录
- 添加 `WeChatWASM` 命名空间
### v1.0.0 (2026-03-02)
- 实现自动注入 EmbeddedAppletSDK GameObject
- 智能检测并复制模板脚本
- 兼容 Windows 和 macOS 构建