mirror of
https://github.com/wechat-miniprogram/minigame-tuanjie-transform-sdk.git
synced 2026-04-22 01:35:56 +08:00
Auto-publish.
This commit is contained in:
parent
f67e7851c3
commit
dd763bcb06
@ -6,7 +6,7 @@ Removed - 删除功能/接口
|
||||
Fixed - 修复问题
|
||||
Others - 其他
|
||||
-->
|
||||
## 2026-3-15 v0.1.32 【普通更新】
|
||||
## 2026-3-16 v0.1.32 【普通更新】
|
||||
### Feature
|
||||
* 普通:更新基础库版本
|
||||
* 普通:擂台赛api新增subScoreKey参数
|
||||
|
||||
174
Editor/PCHighPerformance/PCHPBuildPreProcessor.cs
Normal file
174
Editor/PCHighPerformance/PCHPBuildPreProcessor.cs
Normal file
@ -0,0 +1,174 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.IO;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
/// <summary>
|
||||
/// PC高性能小游戏构建预处理器
|
||||
/// 负责在构建前向首场景注入 WXPCHPInitScript
|
||||
/// </summary>
|
||||
public class PCHPBuildPreProcessor : IPreprocessBuildWithReport
|
||||
{
|
||||
// SDK 脚本名称常量
|
||||
private const string SDK_CLASS_NAME = "WeChatWASM.WXPCHPInitScript";
|
||||
private const string SDK_GAMEOBJECT_NAME = "WXPCHPInitScript";
|
||||
|
||||
public int callbackOrder => 0;
|
||||
|
||||
public void OnPreprocessBuild(BuildReport report)
|
||||
{
|
||||
Debug.Log("========================================");
|
||||
Debug.Log("[PC高性能小游戏] PCHPBuildPreProcessor.OnPreprocessBuild 被调用");
|
||||
Debug.Log("========================================");
|
||||
|
||||
// 只处理 Windows/Mac Standalone 构建
|
||||
var buildTarget = report.summary.platform;
|
||||
if (buildTarget != BuildTarget.StandaloneWindows64 &&
|
||||
buildTarget != BuildTarget.StandaloneOSX)
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能小游戏] 当前平台 {buildTarget} 不是 Windows/Mac,跳过预处理");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("[PC高性能小游戏] 开始预处理构建...");
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Log("[PC高性能小游戏] → 步骤1: 检查 WXPCHPInitScript 脚本是否存在");
|
||||
EnsureSDKScriptExists();
|
||||
|
||||
Debug.Log("[PC高性能小游戏] → 步骤2: 向首场景注入 SDK GameObject");
|
||||
InjectSDKToFirstScene();
|
||||
|
||||
Debug.Log("[PC高性能小游戏] ✅ 预处理完成!");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError("========================================");
|
||||
Debug.LogError($"[PC高性能小游戏] ❌ 预处理失败: {e.Message}\n{e.StackTrace}");
|
||||
Debug.LogError("========================================");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在所有程序集中查找类型
|
||||
/// </summary>
|
||||
private System.Type FindTypeInAllAssemblies(string typeName)
|
||||
{
|
||||
foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
var type = assembly.GetType(typeName);
|
||||
if (type != null)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确保 WXPCHPInitScript 脚本存在
|
||||
/// </summary>
|
||||
private void EnsureSDKScriptExists()
|
||||
{
|
||||
var sdkType = FindTypeInAllAssemblies(SDK_CLASS_NAME);
|
||||
if (sdkType != null)
|
||||
{
|
||||
Debug.Log($"[PC高性能小游戏] ✅ WXPCHPInitScript 脚本已加载 (程序集: {sdkType.Assembly.GetName().Name})");
|
||||
return;
|
||||
}
|
||||
|
||||
// 脚本应该在 SDK Runtime 目录,如果找不到说明 SDK 安装有问题
|
||||
Debug.LogError("[PC高性能小游戏] ❌ 找不到 WXPCHPInitScript 类型");
|
||||
Debug.LogError("[PC高性能小游戏] 请确保 WX-WASM-SDK-V2 已正确安装");
|
||||
throw new BuildFailedException("[PC高性能小游戏] 缺少 WXPCHPInitScript 脚本,请检查 SDK 安装");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向第一个启用的场景注入 SDK GameObject
|
||||
/// </summary>
|
||||
private void InjectSDKToFirstScene()
|
||||
{
|
||||
var firstScenePath = GetFirstEnabledScene();
|
||||
if (string.IsNullOrEmpty(firstScenePath))
|
||||
{
|
||||
Debug.LogWarning("[PC高性能小游戏] 没有找到启用的场景,跳过注入");
|
||||
return;
|
||||
}
|
||||
|
||||
var currentScenes = EditorSceneManager.GetSceneManagerSetup();
|
||||
var scene = EditorSceneManager.OpenScene(firstScenePath, OpenSceneMode.Single);
|
||||
|
||||
// 删除旧的对象(兼容从 EmbeddedAppletSDK 迁移)
|
||||
var oldSDK = GameObject.Find("EmbeddedAppletSDK");
|
||||
if (oldSDK != null)
|
||||
{
|
||||
Debug.Log("[PC高性能小游戏] 删除旧的 EmbeddedAppletSDK 对象");
|
||||
GameObject.DestroyImmediate(oldSDK);
|
||||
}
|
||||
|
||||
// 检查是否已存在新的 SDK 对象
|
||||
var existingSDK = GameObject.Find(SDK_GAMEOBJECT_NAME);
|
||||
if (existingSDK != null)
|
||||
{
|
||||
Debug.Log($"[PC高性能小游戏] 场景中已存在 {SDK_GAMEOBJECT_NAME},重新创建");
|
||||
GameObject.DestroyImmediate(existingSDK);
|
||||
}
|
||||
|
||||
// 创建 GameObject 并添加组件
|
||||
var sdkObject = new GameObject(SDK_GAMEOBJECT_NAME);
|
||||
var sdkType = FindTypeInAllAssemblies(SDK_CLASS_NAME);
|
||||
|
||||
if (sdkType != null)
|
||||
{
|
||||
var assemblyName = sdkType.Assembly.GetName().Name;
|
||||
Debug.Log($"[PC高性能小游戏] 找到 WXPCHPInitScript,程序集: {assemblyName}");
|
||||
|
||||
if (assemblyName.Contains("Editor"))
|
||||
{
|
||||
Debug.LogError("[PC高性能小游戏] ❌ WXPCHPInitScript 在 Editor 程序集中!");
|
||||
GameObject.DestroyImmediate(sdkObject);
|
||||
throw new BuildFailedException("[PC高性能小游戏] WXPCHPInitScript 必须在 Runtime 程序集");
|
||||
}
|
||||
|
||||
sdkObject.AddComponent(sdkType);
|
||||
Debug.Log($"[PC高性能小游戏] ✅ 已在 {scene.name} 中创建 {SDK_GAMEOBJECT_NAME} 并添加组件");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("[PC高性能小游戏] ❌ 找不到 WXPCHPInitScript 类型");
|
||||
GameObject.DestroyImmediate(sdkObject);
|
||||
throw new BuildFailedException("[PC高性能小游戏] 无法找到 WXPCHPInitScript 组件");
|
||||
}
|
||||
|
||||
EditorSceneManager.MarkSceneDirty(scene);
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
RestoreScenes(currentScenes);
|
||||
}
|
||||
|
||||
private string GetFirstEnabledScene()
|
||||
{
|
||||
foreach (var scene in EditorBuildSettings.scenes)
|
||||
{
|
||||
if (scene.enabled)
|
||||
{
|
||||
return scene.path;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void RestoreScenes(UnityEditor.SceneManagement.SceneSetup[] setup)
|
||||
{
|
||||
if (setup != null && setup.Length > 0)
|
||||
{
|
||||
EditorSceneManager.RestoreSceneManagerSetup(setup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Editor/PCHighPerformance/PCHPBuildPreProcessor.cs.meta
Normal file
7
Editor/PCHighPerformance/PCHPBuildPreProcessor.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2764f66c7a7ee9dfaf53ffe5f6215d0
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
110
Editor/PCHighPerformance/README_AutoInjection.md
Normal file
110
Editor/PCHighPerformance/README_AutoInjection.md
Normal file
@ -0,0 +1,110 @@
|
||||
# PC高性能小游戏 - 自动化构建注入
|
||||
|
||||
## 📂 文件结构
|
||||
|
||||
```
|
||||
WX-WASM-SDK-V2/
|
||||
├── Editor/PCHighPerformance/
|
||||
│ ├── PCHPBuildPreProcessor.cs # 构建预处理器(自动注入)
|
||||
│ ├── PCHPDebugHelper.cs # 调试工具
|
||||
│ ├── WXPCSettingHelper.cs # 构建配置助手
|
||||
│ └── WXEditorPCHPWindow.cs # 编辑器窗口
|
||||
└── Runtime/
|
||||
└── WXPCHPInitScript.cs # SDK 运行时脚本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 功能说明
|
||||
|
||||
### 自动注入机制
|
||||
|
||||
**触发时机**:开发者点击「生成并转换」按钮,Unity 开始构建 Windows/macOS 平台前
|
||||
|
||||
**工作流程**:
|
||||
|
||||
```
|
||||
构建开始
|
||||
↓
|
||||
PCHPBuildPreProcessor.OnPreprocessBuild() 触发
|
||||
↓
|
||||
Step 1: 检查 WXPCHPInitScript 是否已加载
|
||||
├── 已加载 → 继续
|
||||
└── 未加载 → 报错中断(SDK 安装问题)
|
||||
↓
|
||||
Step 2: 打开首个启用场景
|
||||
↓
|
||||
Step 3: 检查场景是否已有 "WXPCHPInitScript" GameObject
|
||||
├── 有 → 删除重建
|
||||
└── 没有 → 创建新 GameObject + 添加 WXPCHPInitScript 组件
|
||||
↓
|
||||
Step 4: 保存场景并恢复原始布局
|
||||
↓
|
||||
继续正常构建流程
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 关键特性
|
||||
|
||||
1. **零侵入**:不修改开发者当前打开的场景
|
||||
2. **智能检测**:自动检测是否已存在脚本/对象
|
||||
3. **SDK 内置**:脚本位于 SDK Runtime 目录,无需复制到用户项目
|
||||
4. **命名空间隔离**:使用 `WeChatWASM` 命名空间避免冲突
|
||||
|
||||
---
|
||||
|
||||
## 🔧 配置说明
|
||||
|
||||
### 脚本位置
|
||||
|
||||
```
|
||||
Assets/WX-WASM-SDK-V2/Runtime/WXPCHPInitScript.cs
|
||||
```
|
||||
|
||||
**类名**:`WeChatWASM.WXPCHPInitScript`
|
||||
|
||||
**作用**:运行时初始化 PC 高性能小游戏 SDK,与宿主程序通信
|
||||
|
||||
---
|
||||
|
||||
## 🐛 常见问题
|
||||
|
||||
### Q: 为什么导出的工程没有 SDK 对象?
|
||||
|
||||
检查 Console 日志:
|
||||
- ✅ `[PC高性能小游戏] ✅ 已在 XXX 中创建 WXPCHPInitScript 并添加组件` → 成功
|
||||
- ⚠️ `找不到 WXPCHPInitScript 类型` → SDK 未正确安装
|
||||
|
||||
### Q: DLL 加载失败?
|
||||
|
||||
**原因**:`direct_applet_sdk.dll` 必须在 **运行时** 的根目录(与 .exe 同级)
|
||||
|
||||
**解决**:确保宿主程序启动时提供 DLL
|
||||
|
||||
---
|
||||
|
||||
## 📝 技术细节
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| 触发接口 | `IPreprocessBuildWithReport` |
|
||||
| 回调优先级 | `callbackOrder = 0` |
|
||||
| 支持平台 | Windows x64, macOS |
|
||||
| 场景修改策略 | 临时打开 → 注入 → 保存 → 恢复 |
|
||||
| 类全名 | `WeChatWASM.WXPCHPInitScript` |
|
||||
|
||||
---
|
||||
|
||||
## 🔄 更新日志
|
||||
|
||||
### v1.1.0 (2026-03-02)
|
||||
- ✅ 重命名 `EmbeddedAppletSDK` → `WXPCHPInitScript`
|
||||
- ✅ 迁移脚本到 Runtime 目录(解决 Editor 脚本无法挂载问题)
|
||||
- ✅ 添加 `WeChatWASM` 命名空间
|
||||
- ✅ 移除模板复制机制(脚本现在内置于 SDK)
|
||||
|
||||
### v1.0.0 (2026-03-02)
|
||||
- ✅ 实现自动注入 EmbeddedAppletSDK GameObject
|
||||
- ✅ 智能检测并复制模板脚本
|
||||
- ✅ 兼容 Windows 和 macOS 构建
|
||||
7
Editor/PCHighPerformance/README_AutoInjection.md.meta
Normal file
7
Editor/PCHighPerformance/README_AutoInjection.md.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aacc596790ffe1aad08acb624adcdfaa
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
152
Editor/PCHighPerformance/TROUBLESHOOTING.md
Normal file
152
Editor/PCHighPerformance/TROUBLESHOOTING.md
Normal file
@ -0,0 +1,152 @@
|
||||
# PC高性能小游戏 - 问题排查指南
|
||||
|
||||
## 🐛 问题1:设置面板数据被清空
|
||||
|
||||
### 原因
|
||||
`OnLostFocus()` 时机不对,输入框的值可能还未同步到 `formInputData`
|
||||
|
||||
### 解决方案 ✅
|
||||
已修复:在 `OnSettingsGUI()` 中添加 `GUI.changed` 检测,每次输入时自动保存
|
||||
|
||||
---
|
||||
|
||||
## 🐛 问题2:ShowInfo 逻辑未执行
|
||||
|
||||
### 可能原因
|
||||
|
||||
#### 1. DLL 未找到 (最常见 90%)
|
||||
**症状**:运行 .exe 后没有任何弹窗
|
||||
**原因**:`direct_applet_sdk.dll` 不在 .exe 同级目录
|
||||
|
||||
**验证**:
|
||||
```bash
|
||||
# 检查导出目录结构
|
||||
导出路径/
|
||||
├── YourGame.exe
|
||||
├── direct_applet_sdk.dll ← 必须存在
|
||||
└── YourGame_Data/
|
||||
```
|
||||
|
||||
**解决**:
|
||||
- 确保 DLL 在运行时根目录
|
||||
- 查看 Unity Player.log:
|
||||
- Windows: `%APPDATA%\..\LocalLow\<CompanyName>\<ProductName>\Player.log`
|
||||
- 搜索关键字: `[WXPCHPInitScript]` 或 `DllNotFoundException`
|
||||
|
||||
---
|
||||
|
||||
#### 2. GameObject 未注入 (10%)
|
||||
**症状**:构建后场景中没有 `WXPCHPInitScript` 对象
|
||||
|
||||
**验证**:使用调试工具
|
||||
```
|
||||
Unity 菜单 → 微信小游戏 → PC高性能调试 → 检查SDK注入状态
|
||||
```
|
||||
|
||||
**可能的问题**:
|
||||
- ❌ Build Settings 中没有启用场景
|
||||
- ❌ 构建前 `PCHPBuildPreProcessor` 未执行
|
||||
- ❌ SDK 未正确安装
|
||||
|
||||
**解决**:
|
||||
1. 确保 Build Settings 有至少一个启用场景
|
||||
2. 查看 Console 日志:
|
||||
```
|
||||
[PC高性能小游戏] 开始预处理构建...
|
||||
[PC高性能小游戏] ✅ 已在 XXX 中创建 WXPCHPInitScript 并添加组件
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 调试步骤(按顺序)
|
||||
|
||||
### Step 1: 检查 SDK 注入状态
|
||||
```
|
||||
Unity 菜单 → 微信小游戏 → PC高性能调试 → 检查SDK注入状态
|
||||
```
|
||||
|
||||
✅ 正常输出示例:
|
||||
```
|
||||
[构建场景] 启用的场景数: 1
|
||||
✅ 首场景: Assets/Scenes/Main.unity
|
||||
✅ 找到 SDK GameObject: WXPCHPInitScript
|
||||
✅ 挂载的脚本: WeChatWASM.WXPCHPInitScript
|
||||
|
||||
[类型加载检查]
|
||||
✅ WXPCHPInitScript 类型已加载
|
||||
程序集: WxWasmSDKRuntime
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Step 2: 检查导出路径
|
||||
```
|
||||
Unity 菜单 → 微信小游戏 → PC高性能调试 → 查看导出路径
|
||||
```
|
||||
|
||||
确认:
|
||||
- ✅ 目录存在
|
||||
- ✅ 有 .exe 文件
|
||||
|
||||
---
|
||||
|
||||
### Step 3: 运行 .exe 并查看日志
|
||||
|
||||
**日志位置**:
|
||||
```
|
||||
Windows: %APPDATA%\..\LocalLow\YourCompany\YourProduct\Player.log
|
||||
Mac: ~/Library/Logs/Company Name/Product Name/Player.log
|
||||
```
|
||||
|
||||
**搜索关键字**:
|
||||
```
|
||||
[WXPCHPInitScript]
|
||||
DllNotFoundException
|
||||
InitEmbeddedGameSDK
|
||||
```
|
||||
|
||||
**正常日志**:
|
||||
```
|
||||
[WXPCHPInitScript] ========== Awake 被调用 ==========
|
||||
[WXPCHPInitScript] GameObject 名称: WXPCHPInitScript
|
||||
[WXPCHPInitScript] ========== 开始初始化 ==========
|
||||
[WXPCHPInitScript] Step 1: 调用 InitEmbeddedGameSDK
|
||||
[WXPCHPInitScript] InitEmbeddedGameSDK 成功
|
||||
...
|
||||
```
|
||||
|
||||
**异常日志**:
|
||||
```
|
||||
DllNotFoundException: Unable to load DLL 'direct_applet_sdk.dll'
|
||||
→ 解决: 复制 DLL 到 .exe 同级目录
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 快速检查清单
|
||||
|
||||
- [ ] Build Settings 中有启用的场景
|
||||
- [ ] 构建时 Console 有 `[PC高性能小游戏] 预处理完成!` 日志
|
||||
- [ ] 导出目录包含 `.exe` 和 `direct_applet_sdk.dll`
|
||||
- [ ] 运行 .exe 后有弹窗或 Player.log 有日志
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 调试工具菜单
|
||||
|
||||
| 菜单项 | 功能 |
|
||||
|--------|------|
|
||||
| 检查SDK注入状态 | 验证场景中是否有 SDK 对象和脚本 |
|
||||
| 查看导出路径 | 显示配置的导出路径和状态 |
|
||||
| 打开导出目录 | 在文件管理器中打开导出目录 |
|
||||
|
||||
---
|
||||
|
||||
## 💡 常见错误代码
|
||||
|
||||
| 错误信息 | 原因 | 解决方法 |
|
||||
|----------|------|----------|
|
||||
| `DllNotFoundException` | DLL 未找到 | 复制 DLL 到 .exe 同级目录 |
|
||||
| `EntryPointNotFoundException` | 函数不存在 | 检查 DLL 版本是否匹配 |
|
||||
| `找不到 WXPCHPInitScript 类型` | SDK 未安装 | 重新导入 WX-WASM-SDK-V2 |
|
||||
| `GetActiveWindow 返回空句柄` | 窗口未创建 | 延迟初始化或检查 Unity Player 设置 |
|
||||
7
Editor/PCHighPerformance/TROUBLESHOOTING.md.meta
Normal file
7
Editor/PCHighPerformance/TROUBLESHOOTING.md.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b57398b893716f5822f5e196466fee6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
267
Editor/PCHighPerformance/WXApkgPacker.cs
Normal file
267
Editor/PCHighPerformance/WXApkgPacker.cs
Normal file
@ -0,0 +1,267 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
/// <summary>
|
||||
/// wxapkg 文件打包器
|
||||
/// 将目录内容打包成 .wxapkg 格式
|
||||
///
|
||||
/// wxapkg 格式结构:
|
||||
/// 1. 头部段 (14 字节)
|
||||
/// - 起始标志: 1 字节 (0xBE)
|
||||
/// - 未知字段: 4 字节 (固定为 0)
|
||||
/// - 结束标志: 1 字节 (0xED)
|
||||
/// - 索引段长度: 4 字节 (大端序)
|
||||
/// - 数据段长度: 4 字节 (大端序)
|
||||
/// 2. 索引段
|
||||
/// - 文件数量: 4 字节 (大端序)
|
||||
/// - 文件信息块序列(每个文件):
|
||||
/// - 文件名长度: 4 字节 (大端序)
|
||||
/// - 文件名: 可变长度 (UTF-8)
|
||||
/// - 文件偏移: 4 字节 (大端序)
|
||||
/// - 文件长度: 4 字节 (大端序)
|
||||
/// 3. 数据段
|
||||
/// - 实际文件内容的二进制数据
|
||||
/// </summary>
|
||||
public static class WXApkgPacker
|
||||
{
|
||||
private const byte HEADER_MARK_START = 0xBE;
|
||||
private const byte HEADER_MARK_END = 0xED;
|
||||
private const int HEADER_SIZE = 14;
|
||||
|
||||
/// <summary>
|
||||
/// 文件信息结构
|
||||
/// </summary>
|
||||
private class FileInfo
|
||||
{
|
||||
public string RelativePath; // 相对路径(以 / 开头)
|
||||
public string FullPath; // 完整路径
|
||||
public int Size; // 文件大小
|
||||
public int Offset; // 在数据段中的偏移
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将目录打包成 wxapkg 文件
|
||||
/// </summary>
|
||||
/// <param name="sourceDir">源目录路径</param>
|
||||
/// <param name="outputPath">输出的 wxapkg 文件路径</param>
|
||||
/// <returns>是否成功</returns>
|
||||
public static bool Pack(string sourceDir, string outputPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(sourceDir))
|
||||
{
|
||||
Debug.LogError($"[WXApkgPacker] 源目录不存在: {sourceDir}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 收集所有文件信息
|
||||
var files = CollectFiles(sourceDir);
|
||||
if (files.Count == 0)
|
||||
{
|
||||
Debug.LogError($"[WXApkgPacker] 目录为空: {sourceDir}");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log($"[WXApkgPacker] 收集到 {files.Count} 个文件");
|
||||
|
||||
// 构建索引段
|
||||
byte[] indexData = BuildIndexSection(files);
|
||||
|
||||
// 构建数据段
|
||||
byte[] dataSection = BuildDataSection(files);
|
||||
|
||||
// 构建头部
|
||||
byte[] header = BuildHeader(indexData.Length, dataSection.Length);
|
||||
|
||||
// 确保输出目录存在
|
||||
string outputDir = Path.GetDirectoryName(outputPath);
|
||||
if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
|
||||
{
|
||||
Directory.CreateDirectory(outputDir);
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
using (var fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
fs.Write(header, 0, header.Length);
|
||||
fs.Write(indexData, 0, indexData.Length);
|
||||
fs.Write(dataSection, 0, dataSection.Length);
|
||||
}
|
||||
|
||||
long totalSize = header.Length + indexData.Length + dataSection.Length;
|
||||
Debug.Log($"[WXApkgPacker] 打包完成: {outputPath}");
|
||||
Debug.Log($"[WXApkgPacker] 文件大小: {totalSize / 1024.0 / 1024.0:F2} MB");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXApkgPacker] 打包失败: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 收集目录下所有文件
|
||||
/// </summary>
|
||||
private static List<FileInfo> CollectFiles(string sourceDir)
|
||||
{
|
||||
var files = new List<FileInfo>();
|
||||
var allFiles = Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories);
|
||||
|
||||
foreach (var filePath in allFiles)
|
||||
{
|
||||
// 跳过 .DS_Store 等隐藏文件
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
if (fileName.StartsWith("."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算相对路径(使用正斜杠,以 / 开头)
|
||||
string relativePath = filePath.Substring(sourceDir.Length);
|
||||
relativePath = relativePath.Replace('\\', '/');
|
||||
if (!relativePath.StartsWith("/"))
|
||||
{
|
||||
relativePath = "/" + relativePath;
|
||||
}
|
||||
|
||||
var info = new System.IO.FileInfo(filePath);
|
||||
files.Add(new FileInfo
|
||||
{
|
||||
RelativePath = relativePath,
|
||||
FullPath = filePath,
|
||||
Size = (int)info.Length
|
||||
});
|
||||
}
|
||||
|
||||
// 按路径排序,保持一致性
|
||||
files.Sort((a, b) => string.Compare(a.RelativePath, b.RelativePath, StringComparison.Ordinal));
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建头部段 (14 字节)
|
||||
/// </summary>
|
||||
private static byte[] BuildHeader(int indexLength, int dataLength)
|
||||
{
|
||||
byte[] header = new byte[HEADER_SIZE];
|
||||
|
||||
// 起始标志
|
||||
header[0] = HEADER_MARK_START;
|
||||
|
||||
// 4 字节未知字段 (固定为 0)
|
||||
header[1] = 0;
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
header[4] = 0;
|
||||
|
||||
// 结束标志
|
||||
header[5] = HEADER_MARK_END;
|
||||
|
||||
// 索引段长度 (大端序)
|
||||
WriteInt32BE(header, 6, indexLength);
|
||||
|
||||
// 数据段长度 (大端序)
|
||||
WriteInt32BE(header, 10, dataLength);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建索引段
|
||||
/// </summary>
|
||||
private static byte[] BuildIndexSection(List<FileInfo> files)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var writer = new BinaryWriter(ms))
|
||||
{
|
||||
// 文件数量 (大端序)
|
||||
WriteInt32BE(writer, files.Count);
|
||||
|
||||
// 计算数据段起始偏移
|
||||
// 偏移量 = 头部大小 + 索引段大小
|
||||
// 需要先计算索引段大小
|
||||
int indexSize = 4; // 文件数量
|
||||
foreach (var file in files)
|
||||
{
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(file.RelativePath);
|
||||
indexSize += 4 + nameBytes.Length + 4 + 4; // nameLen + name + offset + size
|
||||
}
|
||||
|
||||
int dataOffset = HEADER_SIZE + indexSize;
|
||||
|
||||
// 写入每个文件的索引信息
|
||||
foreach (var file in files)
|
||||
{
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(file.RelativePath);
|
||||
|
||||
// 文件名长度 (大端序)
|
||||
WriteInt32BE(writer, nameBytes.Length);
|
||||
|
||||
// 文件名
|
||||
writer.Write(nameBytes);
|
||||
|
||||
// 文件偏移 (大端序)
|
||||
file.Offset = dataOffset;
|
||||
WriteInt32BE(writer, dataOffset);
|
||||
|
||||
// 文件大小 (大端序)
|
||||
WriteInt32BE(writer, file.Size);
|
||||
|
||||
// 更新下一个文件的偏移
|
||||
dataOffset += file.Size;
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构建数据段
|
||||
/// </summary>
|
||||
private static byte[] BuildDataSection(List<FileInfo> files)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
byte[] content = File.ReadAllBytes(file.FullPath);
|
||||
ms.Write(content, 0, content.Length);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入 32 位大端序整数到字节数组
|
||||
/// </summary>
|
||||
private static void WriteInt32BE(byte[] buffer, int offset, int value)
|
||||
{
|
||||
buffer[offset] = (byte)((value >> 24) & 0xFF);
|
||||
buffer[offset + 1] = (byte)((value >> 16) & 0xFF);
|
||||
buffer[offset + 2] = (byte)((value >> 8) & 0xFF);
|
||||
buffer[offset + 3] = (byte)(value & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入 32 位大端序整数到流
|
||||
/// </summary>
|
||||
private static void WriteInt32BE(BinaryWriter writer, int value)
|
||||
{
|
||||
writer.Write((byte)((value >> 24) & 0xFF));
|
||||
writer.Write((byte)((value >> 16) & 0xFF));
|
||||
writer.Write((byte)((value >> 8) & 0xFF));
|
||||
writer.Write((byte)(value & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Editor/PCHighPerformance/WXApkgPacker.cs.meta
Normal file
7
Editor/PCHighPerformance/WXApkgPacker.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01b846953f0b79ebc3a6176ea11b6eb6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
395
Editor/PCHighPerformance/WXPCHPBuildHelper.cs
Normal file
395
Editor/PCHighPerformance/WXPCHPBuildHelper.cs
Normal file
@ -0,0 +1,395 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
/// <summary>
|
||||
/// PC高性能小游戏构建辅助类
|
||||
/// 用于在微信小游戏转换工具面板中集成PC高性能模式构建
|
||||
/// </summary>
|
||||
public static class WXPCHPBuildHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// PC高性能构建产物目录名
|
||||
/// </summary>
|
||||
public const string PCHPOutputDir = "pchpcode";
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否开启了PC高性能模式
|
||||
/// </summary>
|
||||
public static bool IsPCHighPerformanceEnabled()
|
||||
{
|
||||
var config = UnityUtil.GetEditorConf();
|
||||
bool enabled = config != null && config.ProjectConf.EnablePCHighPerformance;
|
||||
Debug.Log($"[PC高性能模式] 检查配置: config={config != null}, EnablePCHighPerformance={config?.ProjectConf?.EnablePCHighPerformance}, 结果={enabled}");
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行PC高性能构建
|
||||
/// </summary>
|
||||
/// <param name="exportBasePath">导出基础路径(来自小游戏面板配置)</param>
|
||||
/// <returns>构建是否成功</returns>
|
||||
public static bool BuildPCHighPerformance(string exportBasePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(exportBasePath))
|
||||
{
|
||||
Debug.LogError("[PC高性能模式] 导出路径为空,无法构建");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 确定构建目标平台
|
||||
var currentPlatform = Application.platform;
|
||||
BuildTarget buildTarget;
|
||||
string platformName;
|
||||
|
||||
if (currentPlatform == RuntimePlatform.OSXEditor)
|
||||
{
|
||||
buildTarget = BuildTarget.StandaloneOSX;
|
||||
platformName = "Mac";
|
||||
}
|
||||
else
|
||||
{
|
||||
buildTarget = BuildTarget.StandaloneWindows64;
|
||||
platformName = "Windows";
|
||||
}
|
||||
|
||||
// 构建输出路径:直接放在 minigame/pchpcode 目录下
|
||||
string pchpOutputPath = Path.Combine(exportBasePath, WXConvertCore.miniGameDir, PCHPOutputDir);
|
||||
|
||||
Debug.Log($"[PC高性能模式] 开始构建,目标平台: {platformName}");
|
||||
Debug.Log($"[PC高性能模式] 输出路径: {pchpOutputPath}");
|
||||
|
||||
// 保存当前构建目标
|
||||
var originalTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||
var originalTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||
|
||||
try
|
||||
{
|
||||
// 切换构建目标(如果需要)
|
||||
if (originalTarget != buildTarget)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 切换构建目标: {originalTarget} -> {buildTarget}");
|
||||
if (!EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, buildTarget))
|
||||
{
|
||||
Debug.LogError("[PC高性能模式] 切换构建目标失败");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 配置 Player Settings
|
||||
ConfigurePlayerSettings();
|
||||
|
||||
// 确保输出目录存在
|
||||
if (!Directory.Exists(pchpOutputPath))
|
||||
{
|
||||
Directory.CreateDirectory(pchpOutputPath);
|
||||
}
|
||||
|
||||
// 获取可执行文件路径
|
||||
string executablePath = GetExecutablePath(pchpOutputPath, buildTarget);
|
||||
|
||||
// 获取场景列表
|
||||
var scenes = GetEnabledScenes();
|
||||
if (scenes.Length == 0)
|
||||
{
|
||||
Debug.LogError("[PC高性能模式] 没有启用的场景,请在 Build Settings 中添加场景");
|
||||
EditorUtility.DisplayDialog("PC高性能模式构建失败", "没有启用的场景,请在 Build Settings 中添加场景", "确定");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 构建选项
|
||||
var buildOptions = BuildOptions.None;
|
||||
|
||||
// 执行构建
|
||||
Debug.Log($"[PC高性能模式] 执行构建,输出: {executablePath}");
|
||||
var report = BuildPipeline.BuildPlayer(scenes, executablePath, buildTarget, buildOptions);
|
||||
|
||||
// 检查构建结果
|
||||
if (report.summary.result == BuildResult.Succeeded)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 构建成功! 耗时: {report.summary.totalTime.TotalSeconds:F2}秒");
|
||||
Debug.Log($"[PC高性能模式] 输出路径: {pchpOutputPath}");
|
||||
|
||||
// 打包成 wxapkg 格式(先打包到临时位置)
|
||||
string tempWxapkgPath = Path.Combine(exportBasePath, WXConvertCore.miniGameDir, $"{PCHPOutputDir}_temp.wxapkg");
|
||||
string finalWxapkgPath = Path.Combine(pchpOutputPath, $"{PCHPOutputDir}.wxapkg");
|
||||
|
||||
Debug.Log($"[PC高性能模式] 开始打包 wxapkg...");
|
||||
|
||||
if (WXApkgPacker.Pack(pchpOutputPath, tempWxapkgPath))
|
||||
{
|
||||
// 删除原始构建材料
|
||||
Debug.Log($"[PC高性能模式] 清理原始构建材料...");
|
||||
Directory.Delete(pchpOutputPath, true);
|
||||
|
||||
// 重新创建目录并移动 wxapkg
|
||||
Directory.CreateDirectory(pchpOutputPath);
|
||||
File.Move(tempWxapkgPath, finalWxapkgPath);
|
||||
|
||||
// 创建空的 game.js 文件
|
||||
string gameJsPath = Path.Combine(pchpOutputPath, "game.js");
|
||||
File.WriteAllText(gameJsPath, "");
|
||||
Debug.Log($"[PC高性能模式] 已创建 game.js: {gameJsPath}");
|
||||
|
||||
Debug.Log($"[PC高性能模式] wxapkg 打包完成: {finalWxapkgPath}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[PC高性能模式] wxapkg 打包失败,保留原始构建产物");
|
||||
if (File.Exists(tempWxapkgPath))
|
||||
{
|
||||
File.Delete(tempWxapkgPath);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[PC高性能模式] 构建失败: {report.summary.result}");
|
||||
foreach (var step in report.steps)
|
||||
{
|
||||
foreach (var message in step.messages)
|
||||
{
|
||||
if (message.type == LogType.Error)
|
||||
{
|
||||
Debug.LogError($"[PC高性能模式] 构建错误: {message.content}");
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogError($"[PC高性能模式] 构建异常: {e.Message}");
|
||||
Debug.LogException(e);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 恢复到小游戏构建目标,确保微信小游戏转换工具能正常加载
|
||||
RestoreToMiniGamePlatform();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 恢复到小游戏平台
|
||||
/// 团结引擎使用 WeixinMiniGame,Unity 使用 WebGL
|
||||
/// </summary>
|
||||
private static void RestoreToMiniGamePlatform()
|
||||
{
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
// 团结引擎:切换到 WeixinMiniGame 平台
|
||||
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.WeixinMiniGame)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 切换回 WeixinMiniGame 构建目标");
|
||||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.WeixinMiniGame, BuildTarget.WeixinMiniGame);
|
||||
}
|
||||
|
||||
// 激活微信小游戏子平台
|
||||
ActivateWeixinSubplatform();
|
||||
#else
|
||||
// Unity:切换到 WebGL 平台
|
||||
if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.WebGL)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 切换回 WebGL 构建目标");
|
||||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.WebGL, BuildTarget.WebGL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TUANJIE_2022_3_OR_NEWER
|
||||
/// <summary>
|
||||
/// 激活微信小游戏子平台(通过反射兼容不同版本团结引擎)
|
||||
/// </summary>
|
||||
private static void ActivateWeixinSubplatform()
|
||||
{
|
||||
try
|
||||
{
|
||||
var miniGameType = typeof(PlayerSettings).GetNestedType("MiniGame");
|
||||
if (miniGameType == null)
|
||||
{
|
||||
Debug.LogWarning("[PC高性能模式] 未找到 PlayerSettings.MiniGame 类型");
|
||||
return;
|
||||
}
|
||||
|
||||
var methods = miniGameType.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
|
||||
System.Reflection.MethodInfo setActiveMethod = null;
|
||||
|
||||
foreach (var m in methods)
|
||||
{
|
||||
if (m.Name == "SetActiveSubplatform")
|
||||
{
|
||||
setActiveMethod = m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (setActiveMethod == null)
|
||||
{
|
||||
Debug.LogWarning("[PC高性能模式] 未找到 SetActiveSubplatform 方法");
|
||||
return;
|
||||
}
|
||||
|
||||
var parameters = setActiveMethod.GetParameters();
|
||||
if (parameters.Length != 2)
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能模式] SetActiveSubplatform 参数数量异常: {parameters.Length}");
|
||||
return;
|
||||
}
|
||||
|
||||
var firstParamType = parameters[0].ParameterType;
|
||||
|
||||
if (firstParamType.IsEnum)
|
||||
{
|
||||
// 枚举版本:尝试多个可能的枚举值名称
|
||||
string[] enumNames = { "WeChat", "Weixin", "WeiXin" };
|
||||
foreach (var name in enumNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
var enumValue = System.Enum.Parse(firstParamType, name);
|
||||
setActiveMethod.Invoke(null, new object[] { enumValue, true });
|
||||
Debug.Log($"[PC高性能模式] 已激活微信小游戏子平台 (enum: {name})");
|
||||
return;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// 如果上面都没命中,打印所有可用枚举值帮助排查
|
||||
var allNames = System.Enum.GetNames(firstParamType);
|
||||
Debug.LogWarning($"[PC高性能模式] 未找到匹配的枚举值,可用值: {string.Join(", ", allNames)}");
|
||||
}
|
||||
else if (firstParamType == typeof(string))
|
||||
{
|
||||
// 字符串版本:按优先级尝试多个可能的标识符
|
||||
// "weixin" 与命令行参数 -minigamesubplatform weixin 一致
|
||||
string[] candidates = { "weixin", "WeChat", "Weixin", "wechat", "WeChat:微信小游戏" };
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
try
|
||||
{
|
||||
setActiveMethod.Invoke(null, new object[] { candidate, true });
|
||||
Debug.Log($"[PC高性能模式] 已激活微信小游戏子平台 (name: {candidate})");
|
||||
return;
|
||||
}
|
||||
catch (System.Reflection.TargetInvocationException ex)
|
||||
{
|
||||
// 内部抛出异常说明名称不对,继续尝试下一个
|
||||
Debug.Log($"[PC高性能模式] 尝试子平台名称 \"{candidate}\" 失败: {ex.InnerException?.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogWarning("[PC高性能模式] 所有候选子平台名称均失败");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能模式] SetActiveSubplatform 参数类型未知: {firstParamType}");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能模式] 激活微信小游戏子平台失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 配置 Player Settings 用于 PC 高性能构建
|
||||
/// </summary>
|
||||
private static void ConfigurePlayerSettings()
|
||||
{
|
||||
// 设置窗口模式
|
||||
PlayerSettings.fullScreenMode = FullScreenMode.Windowed;
|
||||
|
||||
// 设置默认分辨率
|
||||
PlayerSettings.defaultScreenWidth = 1280;
|
||||
PlayerSettings.defaultScreenHeight = 720;
|
||||
|
||||
// 允许调整窗口大小
|
||||
PlayerSettings.resizableWindow = true;
|
||||
|
||||
// 处理 Windows 上 Linear 色彩空间与图形 API 的兼容性问题
|
||||
if (Application.platform == RuntimePlatform.WindowsEditor)
|
||||
{
|
||||
ConfigureWindowsGraphicsAPI();
|
||||
}
|
||||
|
||||
Debug.Log("[PC高性能模式] Player Settings 配置完成");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置 Windows 图形 API,解决 Linear 色彩空间兼容性问题
|
||||
/// </summary>
|
||||
private static void ConfigureWindowsGraphicsAPI()
|
||||
{
|
||||
// 检查当前色彩空间
|
||||
bool isLinear = PlayerSettings.colorSpace == ColorSpace.Linear;
|
||||
|
||||
if (isLinear)
|
||||
{
|
||||
// Linear 色彩空间需要 DX11 或更高版本
|
||||
// 禁用自动图形 API,手动指定兼容的 API
|
||||
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.StandaloneWindows64, false);
|
||||
|
||||
var graphicsAPIs = new UnityEngine.Rendering.GraphicsDeviceType[]
|
||||
{
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Direct3D11,
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Direct3D12,
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Vulkan
|
||||
};
|
||||
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.StandaloneWindows64, graphicsAPIs);
|
||||
Debug.Log("[PC高性能模式] 已配置 Windows 图形 API: D3D11, D3D12, Vulkan(Linear 色彩空间兼容)");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gamma 色彩空间,使用默认图形 API 即可
|
||||
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.StandaloneWindows64, true);
|
||||
Debug.Log("[PC高性能模式] 使用默认 Windows 图形 API(Gamma 色彩空间)");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可执行文件路径
|
||||
/// </summary>
|
||||
private static string GetExecutablePath(string outputPath, BuildTarget target)
|
||||
{
|
||||
string productName = PlayerSettings.productName;
|
||||
if (string.IsNullOrEmpty(productName))
|
||||
{
|
||||
productName = "Game";
|
||||
}
|
||||
|
||||
if (target == BuildTarget.StandaloneOSX)
|
||||
{
|
||||
return Path.Combine(outputPath, $"{productName}.app");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Path.Combine(outputPath, $"{productName}.exe");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取启用的场景列表
|
||||
/// </summary>
|
||||
private static string[] GetEnabledScenes()
|
||||
{
|
||||
var scenes = new List<string>();
|
||||
foreach (var scene in EditorBuildSettings.scenes)
|
||||
{
|
||||
if (scene.enabled)
|
||||
{
|
||||
scenes.Add(scene.path);
|
||||
}
|
||||
}
|
||||
return scenes.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Editor/PCHighPerformance/WXPCHPBuildHelper.cs.meta
Normal file
7
Editor/PCHighPerformance/WXPCHPBuildHelper.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1455a91f4635862b70423ea92eff07bb
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
39
Editor/PCHighPerformance/WXPCHPWindow.cs
Normal file
39
Editor/PCHighPerformance/WXPCHPWindow.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
|
||||
public class WXPCHPWin : EditorWindow
|
||||
{
|
||||
[MenuItem("微信小游戏 / 转换PC高性能模式", false, 3)]
|
||||
public static void Open()
|
||||
{
|
||||
var win = GetWindow(typeof(WXPCHPWin), false, "PC高性能模式转换工具");
|
||||
win.minSize = new Vector2(350, 200);
|
||||
win.position = new Rect(150, 150, 500, 300);
|
||||
win.Show();
|
||||
}
|
||||
|
||||
public void OnFocus()
|
||||
{
|
||||
WXPCSettingsHelperInterface.helper.OnFocus();
|
||||
}
|
||||
|
||||
public void OnLostFocus()
|
||||
{
|
||||
WXPCSettingsHelperInterface.helper.OnLostFocus();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
WXPCSettingsHelperInterface.helper.OnDisable();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
WXPCSettingsHelperInterface.helper.OnSettingsGUI(this);
|
||||
WXPCSettingsHelperInterface.helper.OnBuildButtonGUI(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Editor/PCHighPerformance/WXPCHPWindow.cs.meta
Normal file
7
Editor/PCHighPerformance/WXPCHPWindow.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3e8e576b56fc74b9401b1ef3cd42e06
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
488
Editor/PCHighPerformance/WXPCSettingHelper.cs
Normal file
488
Editor/PCHighPerformance/WXPCSettingHelper.cs
Normal file
@ -0,0 +1,488 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.IO;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class WXPCSettingsHelperInterface
|
||||
{
|
||||
public static WXPCSettingHelper helper = new WXPCSettingHelper();
|
||||
}
|
||||
|
||||
public class WXPCSettingHelper
|
||||
{
|
||||
public static string projectRootPath;
|
||||
|
||||
// SDK 脚本常量
|
||||
private const string SDK_CLASS_NAME = "WeChatWASM.WXPCHPInitScript";
|
||||
private const string SDK_GAMEOBJECT_NAME = "WXPCHPInitScript";
|
||||
|
||||
public WXPCSettingHelper()
|
||||
{
|
||||
projectRootPath = Path.GetFullPath(Application.dataPath + "/../");
|
||||
}
|
||||
|
||||
// UI 状态
|
||||
private Vector2 scrollRoot;
|
||||
|
||||
// 表单数据
|
||||
private Dictionary<string, string> formInputData = new Dictionary<string, string>();
|
||||
|
||||
// 配置文件路径
|
||||
private string ConfigFilePath => Path.Combine(Application.dataPath, "WX-WASM-SDK-V2", "Editor", "PCHighPerformance", "PCHPConfig.json");
|
||||
|
||||
public void OnFocus()
|
||||
{
|
||||
LoadData();
|
||||
}
|
||||
|
||||
public void OnLostFocus()
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
|
||||
public void OnSettingsGUI(EditorWindow window)
|
||||
{
|
||||
scrollRoot = EditorGUILayout.BeginScrollView(scrollRoot);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// 标题
|
||||
var titleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 14,
|
||||
alignment = TextAnchor.MiddleCenter
|
||||
};
|
||||
EditorGUILayout.LabelField("PC高性能模式转换", titleStyle);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
|
||||
|
||||
// 导出路径 - 支持相对路径和选择目录
|
||||
FormInputWithFolderSelectorAndHelp("exportPath", "导出路径", "Standalone 构建产物的输出目录,支持相对路径(相对项目根目录)或绝对路径");
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// 提示信息
|
||||
EditorGUILayout.HelpBox(
|
||||
"点击「生成并转换」将执行以下操作:\n" +
|
||||
"1. 向首场景注入 WXPCHPInitScript 脚本\n" +
|
||||
"2. 构建 Standalone 可执行文件\n" +
|
||||
"3. SDK 初始化时会弹窗展示各步骤进度",
|
||||
MessageType.Info);
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
// 检测 GUI 变化并自动保存
|
||||
if (GUI.changed)
|
||||
{
|
||||
SaveData();
|
||||
}
|
||||
}
|
||||
|
||||
public void OnBuildButtonGUI(EditorWindow window)
|
||||
{
|
||||
EditorGUILayout.Space(5);
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
// 生成并转换按钮
|
||||
var buttonStyle = new GUIStyle(GUI.skin.button)
|
||||
{
|
||||
fontSize = 13,
|
||||
fontStyle = FontStyle.Bold
|
||||
};
|
||||
if (GUILayout.Button("生成并转换", buttonStyle, GUILayout.Width(160), GUILayout.Height(36)))
|
||||
{
|
||||
OnBuildButtonClicked(window);
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.Space(10);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击生成并转换按钮
|
||||
/// </summary>
|
||||
private void OnBuildButtonClicked(EditorWindow window)
|
||||
{
|
||||
SaveData();
|
||||
|
||||
var exportPath = GetDataInput("exportPath");
|
||||
if (string.IsNullOrEmpty(exportPath.Trim()))
|
||||
{
|
||||
EditorUtility.DisplayDialog("错误", "请先设置导出路径", "确定");
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算完整输出路径
|
||||
string fullExportPath;
|
||||
if (Path.IsPathRooted(exportPath))
|
||||
{
|
||||
fullExportPath = exportPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullExportPath = Path.Combine(projectRootPath, exportPath);
|
||||
}
|
||||
|
||||
Debug.Log($"[PC高性能模式] 导出路径: {fullExportPath}");
|
||||
|
||||
// 确定构建平台
|
||||
BuildTarget buildTarget;
|
||||
string platformName;
|
||||
if (Application.platform == RuntimePlatform.OSXEditor)
|
||||
{
|
||||
buildTarget = BuildTarget.StandaloneOSX;
|
||||
platformName = "macOS";
|
||||
}
|
||||
else
|
||||
{
|
||||
buildTarget = BuildTarget.StandaloneWindows64;
|
||||
platformName = "Windows x64";
|
||||
}
|
||||
|
||||
Debug.Log($"[PC高性能模式] 目标平台: {platformName}");
|
||||
|
||||
try
|
||||
{
|
||||
// Step 1: 注入 WXPCHPInitScript 到首场景
|
||||
EditorUtility.DisplayProgressBar("PC高性能模式", "正在向首场景注入 SDK 脚本...", 0.1f);
|
||||
InjectSDKToFirstScene();
|
||||
|
||||
// Step 2: 切换构建目标
|
||||
EditorUtility.DisplayProgressBar("PC高性能模式", "正在切换构建目标...", 0.2f);
|
||||
var originalTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||
if (originalTarget != buildTarget)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 切换构建目标: {originalTarget} -> {buildTarget}");
|
||||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, buildTarget);
|
||||
}
|
||||
|
||||
// Step 3: 配置 Player Settings
|
||||
EditorUtility.DisplayProgressBar("PC高性能模式", "正在配置 Player Settings...", 0.3f);
|
||||
ConfigurePlayerSettings();
|
||||
|
||||
// Step 4: 准备输出目录
|
||||
if (!Directory.Exists(fullExportPath))
|
||||
{
|
||||
Directory.CreateDirectory(fullExportPath);
|
||||
}
|
||||
|
||||
string productName = PlayerSettings.productName;
|
||||
if (string.IsNullOrEmpty(productName)) productName = "Game";
|
||||
|
||||
string executablePath = buildTarget == BuildTarget.StandaloneOSX
|
||||
? Path.Combine(fullExportPath, $"{productName}.app")
|
||||
: Path.Combine(fullExportPath, $"{productName}.exe");
|
||||
|
||||
// Step 5: 获取场景列表
|
||||
var scenes = GetEnabledScenes();
|
||||
if (scenes.Length == 0)
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
EditorUtility.DisplayDialog("构建失败", "没有启用的场景,请在 Build Settings 中添加场景", "确定");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 6: 执行构建
|
||||
EditorUtility.DisplayProgressBar("PC高性能模式", "正在构建 Standalone...", 0.5f);
|
||||
Debug.Log($"[PC高性能模式] 开始构建,输出: {executablePath}");
|
||||
|
||||
var report = BuildPipeline.BuildPlayer(scenes, executablePath, buildTarget, BuildOptions.None);
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
if (report.summary.result == BuildResult.Succeeded)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 构建成功! 耗时: {report.summary.totalTime.TotalSeconds:F2}秒");
|
||||
|
||||
if (EditorUtility.DisplayDialog("构建成功",
|
||||
$"PC高性能模式构建完成!\n\n平台: {platformName}\n耗时: {report.summary.totalTime.TotalSeconds:F2}秒\n输出: {fullExportPath}",
|
||||
"打开目录", "关闭"))
|
||||
{
|
||||
EditorUtility.RevealInFinder(fullExportPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[PC高性能模式] 构建失败: {report.summary.result}");
|
||||
EditorUtility.DisplayDialog("构建失败", $"构建失败: {report.summary.result}\n\n请查看 Console 获取详细错误信息", "确定");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
Debug.LogError($"[PC高性能模式] 构建异常: {e.Message}\n{e.StackTrace}");
|
||||
EditorUtility.DisplayDialog("构建异常", $"构建过程中发生异常:\n{e.Message}", "确定");
|
||||
}
|
||||
}
|
||||
|
||||
#region Scene Injection
|
||||
|
||||
/// <summary>
|
||||
/// 向首场景注入 WXPCHPInitScript
|
||||
/// </summary>
|
||||
private void InjectSDKToFirstScene()
|
||||
{
|
||||
// 查找脚本类型
|
||||
var sdkType = FindTypeInAllAssemblies(SDK_CLASS_NAME);
|
||||
if (sdkType == null)
|
||||
{
|
||||
throw new System.Exception($"找不到 {SDK_CLASS_NAME} 类型,请确保 WX-WASM-SDK-V2 已正确安装");
|
||||
}
|
||||
|
||||
var assemblyName = sdkType.Assembly.GetName().Name;
|
||||
Debug.Log($"[PC高性能模式] 找到 WXPCHPInitScript,程序集: {assemblyName}");
|
||||
|
||||
if (assemblyName.Contains("Editor"))
|
||||
{
|
||||
throw new System.Exception("WXPCHPInitScript 在 Editor 程序集中,无法用于 Runtime 构建!请确保脚本放在 Runtime 目录下");
|
||||
}
|
||||
|
||||
// 获取首场景
|
||||
var firstScenePath = GetFirstEnabledScenePath();
|
||||
if (string.IsNullOrEmpty(firstScenePath))
|
||||
{
|
||||
throw new System.Exception("没有启用的场景,请在 Build Settings 中添加场景");
|
||||
}
|
||||
|
||||
// 打开首场景
|
||||
var currentScenes = EditorSceneManager.GetSceneManagerSetup();
|
||||
var scene = EditorSceneManager.OpenScene(firstScenePath, OpenSceneMode.Single);
|
||||
|
||||
// 清理旧对象
|
||||
var oldSDK = GameObject.Find("EmbeddedAppletSDK");
|
||||
if (oldSDK != null)
|
||||
{
|
||||
Debug.Log("[PC高性能模式] 删除旧的 EmbeddedAppletSDK 对象");
|
||||
GameObject.DestroyImmediate(oldSDK);
|
||||
}
|
||||
|
||||
// 删除已存在的同名对象(避免重复)
|
||||
var existingSDK = GameObject.Find(SDK_GAMEOBJECT_NAME);
|
||||
if (existingSDK != null)
|
||||
{
|
||||
Debug.Log($"[PC高性能模式] 删除已存在的 {SDK_GAMEOBJECT_NAME},重新创建");
|
||||
GameObject.DestroyImmediate(existingSDK);
|
||||
}
|
||||
|
||||
// 创建新的 GameObject 并添加 WXPCHPInitScript
|
||||
var sdkObject = new GameObject(SDK_GAMEOBJECT_NAME);
|
||||
sdkObject.AddComponent(sdkType);
|
||||
Debug.Log($"[PC高性能模式] ✅ 已在场景 [{scene.name}] 创建 {SDK_GAMEOBJECT_NAME} 并挂载 WXPCHPInitScript");
|
||||
|
||||
// 保存场景
|
||||
EditorSceneManager.MarkSceneDirty(scene);
|
||||
EditorSceneManager.SaveScene(scene);
|
||||
|
||||
// 恢复场景状态
|
||||
if (currentScenes != null && currentScenes.Length > 0)
|
||||
{
|
||||
EditorSceneManager.RestoreSceneManagerSetup(currentScenes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在所有程序集中查找类型
|
||||
/// </summary>
|
||||
private System.Type FindTypeInAllAssemblies(string typeName)
|
||||
{
|
||||
foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
var type = assembly.GetType(typeName);
|
||||
if (type != null) return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取首个启用的场景路径
|
||||
/// </summary>
|
||||
private string GetFirstEnabledScenePath()
|
||||
{
|
||||
foreach (var scene in EditorBuildSettings.scenes)
|
||||
{
|
||||
if (scene.enabled) return scene.path;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Build Configuration
|
||||
|
||||
/// <summary>
|
||||
/// 配置 Player Settings
|
||||
/// </summary>
|
||||
private void ConfigurePlayerSettings()
|
||||
{
|
||||
PlayerSettings.fullScreenMode = FullScreenMode.Windowed;
|
||||
PlayerSettings.defaultScreenWidth = 1280;
|
||||
PlayerSettings.defaultScreenHeight = 720;
|
||||
PlayerSettings.resizableWindow = true;
|
||||
|
||||
// Windows Linear 色彩空间需要 DX11+
|
||||
if (Application.platform == RuntimePlatform.WindowsEditor &&
|
||||
PlayerSettings.colorSpace == ColorSpace.Linear)
|
||||
{
|
||||
PlayerSettings.SetUseDefaultGraphicsAPIs(BuildTarget.StandaloneWindows64, false);
|
||||
PlayerSettings.SetGraphicsAPIs(BuildTarget.StandaloneWindows64, new[]
|
||||
{
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Direct3D11,
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Direct3D12,
|
||||
UnityEngine.Rendering.GraphicsDeviceType.Vulkan
|
||||
});
|
||||
}
|
||||
|
||||
Debug.Log("[PC高性能模式] Player Settings 配置完成");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取启用的场景列表
|
||||
/// </summary>
|
||||
private string[] GetEnabledScenes()
|
||||
{
|
||||
var scenes = new List<string>();
|
||||
foreach (var scene in EditorBuildSettings.scenes)
|
||||
{
|
||||
if (scene.enabled) scenes.Add(scene.path);
|
||||
}
|
||||
return scenes.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Data Persistence
|
||||
|
||||
private void LoadData()
|
||||
{
|
||||
if (File.Exists(ConfigFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = File.ReadAllText(ConfigFilePath);
|
||||
var config = JsonUtility.FromJson<PCHPConfigData>(json);
|
||||
if (config != null)
|
||||
{
|
||||
SetData("exportPath", config.exportPath ?? "");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能模式] 加载配置失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetData("exportPath", "");
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveData()
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = new PCHPConfigData
|
||||
{
|
||||
exportPath = GetDataInput("exportPath")
|
||||
};
|
||||
|
||||
var directory = Path.GetDirectoryName(ConfigFilePath);
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var json = JsonUtility.ToJson(config, true);
|
||||
File.WriteAllText(ConfigFilePath, json);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[PC高性能模式] 保存配置失败: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDataInput(string target)
|
||||
{
|
||||
return formInputData.ContainsKey(target) ? formInputData[target] : "";
|
||||
}
|
||||
|
||||
private void SetData(string target, string value)
|
||||
{
|
||||
formInputData[target] = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GUI Helpers
|
||||
|
||||
/// <summary>
|
||||
/// 绘制带文件夹选择器和帮助提示的输入框
|
||||
/// </summary>
|
||||
private void FormInputWithFolderSelectorAndHelp(string target, string label, string help = null)
|
||||
{
|
||||
if (!formInputData.ContainsKey(target))
|
||||
{
|
||||
formInputData[target] = "";
|
||||
}
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(string.Empty, GUILayout.Width(10));
|
||||
|
||||
var displayLabel = help == null ? label : $"{label}(?)";
|
||||
GUILayout.Label(new GUIContent(displayLabel, help), GUILayout.Width(140));
|
||||
|
||||
formInputData[target] = GUILayout.TextField(formInputData[target], GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 275));
|
||||
|
||||
if (GUILayout.Button("选择", GUILayout.Width(60)))
|
||||
{
|
||||
var selectedPath = EditorUtility.OpenFolderPanel("选择导出目录", projectRootPath, "");
|
||||
if (!string.IsNullOrEmpty(selectedPath))
|
||||
{
|
||||
if (selectedPath.StartsWith(projectRootPath))
|
||||
{
|
||||
var relativePath = selectedPath.Substring(projectRootPath.Length);
|
||||
if (relativePath.StartsWith("/") || relativePath.StartsWith("\\"))
|
||||
{
|
||||
relativePath = relativePath.Substring(1);
|
||||
}
|
||||
formInputData[target] = relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
formInputData[target] = selectedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PC高性能小游戏配置数据
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class PCHPConfigData
|
||||
{
|
||||
public string exportPath;
|
||||
}
|
||||
}
|
||||
7
Editor/PCHighPerformance/WXPCSettingHelper.cs.meta
Normal file
7
Editor/PCHighPerformance/WXPCSettingHelper.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 769878c6cc6489f59f3bca6835614c27
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -167,8 +167,10 @@ namespace WeChatWASM
|
||||
Debug.LogError("性能分析工具只能用于Development Build, 终止导出!");
|
||||
return WXExportError.BUILD_WEBGL_FAILED;
|
||||
}
|
||||
dynamic config = isPlayableBuild ? UnityUtil.GetPlayableEditorConf() : UnityUtil.GetEditorConf();
|
||||
if (config.ProjectConf.relativeDST == string.Empty)
|
||||
string relativeDST = isPlayableBuild
|
||||
? UnityUtil.GetPlayableEditorConf().ProjectConf.relativeDST
|
||||
: UnityUtil.GetEditorConf().ProjectConf.relativeDST;
|
||||
if (relativeDST == string.Empty)
|
||||
{
|
||||
Debug.LogError("请先配置游戏导出路径");
|
||||
return WXExportError.BUILD_WEBGL_FAILED;
|
||||
@ -273,6 +275,24 @@ namespace WeChatWASM
|
||||
finishExport();
|
||||
}
|
||||
}
|
||||
|
||||
// PC高性能模式:在小游戏构建完成后构建PC版本
|
||||
if (buildWebGL && WXPCHPBuildHelper.IsPCHighPerformanceEnabled())
|
||||
{
|
||||
Debug.Log("[微信小游戏] 小游戏构建完成,开始构建PC高性能版本...");
|
||||
|
||||
if (!WXPCHPBuildHelper.BuildPCHighPerformance(config.ProjectConf.DST))
|
||||
{
|
||||
Debug.LogError("[微信小游戏] PC高性能模式构建失败");
|
||||
EditorUtility.DisplayDialog("PC高性能模式构建失败",
|
||||
"PC高性能版本构建失败,但小游戏版本已构建成功。", "确定");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("[微信小游戏] PC高性能版本构建完成!");
|
||||
}
|
||||
}
|
||||
|
||||
return WXExportError.SUCCEED;
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +121,14 @@ namespace WeChatWASM
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
foldPCHighPerformance = EditorGUILayout.Foldout(foldPCHighPerformance, "PC高性能模式选项");
|
||||
if (foldPCHighPerformance)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
|
||||
OnSettingPCHighPerformance();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
foldDebugOptions = EditorGUILayout.Foldout(foldDebugOptions, "调试编译选项");
|
||||
if (foldDebugOptions)
|
||||
{
|
||||
@ -233,6 +241,14 @@ namespace WeChatWASM
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
foldPCHighPerformance = EditorGUILayout.Foldout(foldPCHighPerformance, "PC高性能模式");
|
||||
if (foldPCHighPerformance)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
|
||||
OnSettingPCHighPerformance();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
foldDebugOptions = EditorGUILayout.Foldout(foldDebugOptions, "调试编译选项");
|
||||
if (foldDebugOptions)
|
||||
{
|
||||
@ -261,7 +277,7 @@ namespace WeChatWASM
|
||||
{
|
||||
var ProjectConf = miniGameProperty.FindPropertyRelative("ProjectConf");
|
||||
string identifier = ProjectConf.FindPropertyRelative("bundlePathIdentifier").stringValue;
|
||||
string[] identifiers = identifier.Split(";");
|
||||
string[] identifiers = identifier.Split(';');
|
||||
string idStr = "";
|
||||
foreach (string id in identifiers)
|
||||
{
|
||||
@ -374,6 +390,11 @@ namespace WeChatWASM
|
||||
formCheckbox("disableMultiTouch", "禁止多点触控");
|
||||
}
|
||||
|
||||
private void OnSettingPCHighPerformance()
|
||||
{
|
||||
formCheckbox("enablePCHighPerformance", "PC高性能模式(?)", "勾选后将在构建时同时构建PC端高性能版本,构建产物会放到导出路径下的PCHP目录");
|
||||
}
|
||||
|
||||
private void OnSettingDebugOptions(bool showDevBuild)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
|
||||
@ -519,6 +540,7 @@ namespace WeChatWASM
|
||||
private bool foldBaseInfo = true;
|
||||
private bool foldLoadingConfig = true;
|
||||
private bool foldSDKOptions = true;
|
||||
private bool foldPCHighPerformance = true;
|
||||
private bool foldDebugOptions = true;
|
||||
private bool foldInstantGame = false;
|
||||
private bool foldFontOptions = false;
|
||||
@ -657,6 +679,7 @@ namespace WeChatWASM
|
||||
this.setData("loadingBarWidth", ProjectConf.loadingBarWidth.ToString());
|
||||
this.setData("needCheckUpdate", ProjectConf.needCheckUpdate);
|
||||
this.setData("disableHighPerformanceFallback", ProjectConf.disableHighPerformanceFallback);
|
||||
this.setData("enablePCHighPerformance", ProjectConf.EnablePCHighPerformance);
|
||||
}
|
||||
|
||||
private void loadSDKOptionsData(SDKOptions SDKOptions)
|
||||
@ -784,6 +807,7 @@ namespace WeChatWASM
|
||||
ProjectConf.loadingBarWidth = int.Parse(this.getDataInput("loadingBarWidth"));
|
||||
ProjectConf.needCheckUpdate = this.getDataCheckbox("needCheckUpdate");
|
||||
ProjectConf.disableHighPerformanceFallback = this.getDataCheckbox("disableHighPerformanceFallback");
|
||||
ProjectConf.EnablePCHighPerformance = this.getDataCheckbox("enablePCHighPerformance");
|
||||
}
|
||||
|
||||
private void saveSDKOptionsData(SDKOptions SDKOptions)
|
||||
@ -873,6 +897,7 @@ namespace WeChatWASM
|
||||
_ProjectConf.loadingBarWidth = ProjectConf.FindPropertyRelative("loadingBarWidth").intValue;
|
||||
_ProjectConf.needCheckUpdate = ProjectConf.FindPropertyRelative("needCheckUpdate").boolValue;
|
||||
_ProjectConf.disableHighPerformanceFallback = ProjectConf.FindPropertyRelative("disableHighPerformanceFallback").boolValue;
|
||||
_ProjectConf.EnablePCHighPerformance = ProjectConf.FindPropertyRelative("EnablePCHighPerformance").boolValue;
|
||||
}
|
||||
private void serializeProjectConf(WXProjectConf _ProjectConf, SerializedProperty ProjectConf)
|
||||
{
|
||||
@ -902,6 +927,7 @@ namespace WeChatWASM
|
||||
ProjectConf.FindPropertyRelative("loadingBarWidth").intValue = _ProjectConf.loadingBarWidth;
|
||||
ProjectConf.FindPropertyRelative("needCheckUpdate").boolValue = _ProjectConf.needCheckUpdate;
|
||||
ProjectConf.FindPropertyRelative("disableHighPerformanceFallback").boolValue = _ProjectConf.disableHighPerformanceFallback;
|
||||
ProjectConf.FindPropertyRelative("EnablePCHighPerformance").boolValue = _ProjectConf.EnablePCHighPerformance;
|
||||
|
||||
//miniGameProperty.FindPropertyRelative("m_AutomaticFillInstantGame").boolValue = getDataCheckbox("m_AutomaticFillInstantGame");
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ namespace WeChatWASM
|
||||
{
|
||||
public class WXPluginVersion
|
||||
{
|
||||
public static string pluginVersion = "202603160259"; // 这一行不要改他,导出的时候会自动替换
|
||||
public static string pluginVersion = "202604020915"; // 这一行不要改他,导出的时候会自动替换
|
||||
}
|
||||
|
||||
public class WXPluginConf
|
||||
|
||||
Binary file not shown.
@ -493,6 +493,11 @@
|
||||
注意:不要随意修改,默认值为0,0表示不限制
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:WeChatWASM.WXProjectConf.EnablePCHighPerformance">
|
||||
<summary>
|
||||
是否开启PC高性能模式
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:WeChatWASM.CompressTexture.halfSize">
|
||||
<summary>
|
||||
自动将图片尺寸减小一半
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7330c57dbe403f6a6825fe311f4436ca
|
||||
guid: 0f3c8e4abc7778dcf7afb3f801eedac6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59f30477a8bb77aeb6d56b69f0799388
|
||||
guid: 3c4e132ea08f5e5a107ea8baf0cbf5ff
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33778f932d74b9c0309d7573c86c9e5b
|
||||
guid: 3899a1b75c5ff784f41feb320b463939
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1195,8 +1195,38 @@ namespace WeChatWASM
|
||||
public static WXRankManager GetRankManager() {
|
||||
return WXSDKManagerHandler.Instance.GetRankManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PC高性能小游戏
|
||||
/// <summary>
|
||||
/// 获取 PC 高性能小游戏管理器
|
||||
/// 类似于 VA 方案的 wx.getAndroidHighPerformanceManager()
|
||||
/// 用于在 PC 原生环境下与微信基础库通信
|
||||
/// </summary>
|
||||
/// <returns>PC高性能管理器实例,如果不支持则返回 null</returns>
|
||||
/// <example>
|
||||
/// var pcManager = WX.GetPCHighPerformanceManager();
|
||||
/// if (pcManager != null && pcManager.IsSupported)
|
||||
/// {
|
||||
/// pcManager.ShowToast(new PCHPShowToastOption
|
||||
/// {
|
||||
/// title = "Hello PC!",
|
||||
/// icon = "success",
|
||||
/// duration = 2000
|
||||
/// });
|
||||
/// }
|
||||
/// </example>
|
||||
public static WXPCHighPerformanceManager GetPCHighPerformanceManager()
|
||||
{
|
||||
#if UNITY_STANDALONE_WIN
|
||||
return WXPCHighPerformanceManager.GetInstance();
|
||||
#else
|
||||
Debug.LogWarning("[WX] GetPCHighPerformanceManager 仅在 Windows 平台可用");
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
972
Runtime/WXPCHPInitScript.cs
Normal file
972
Runtime/WXPCHPInitScript.cs
Normal file
@ -0,0 +1,972 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using LitJson;
|
||||
|
||||
namespace WeChatWASM
|
||||
{
|
||||
#region Message Protocol Models
|
||||
|
||||
/// <summary>
|
||||
/// PC高性能方案通信协议 - 请求消息
|
||||
/// C# -> DLL -> 内核 -> 基础库
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPRequestMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息类型: "request" | "event_register" | "event_unregister"
|
||||
/// </summary>
|
||||
public string type;
|
||||
|
||||
/// <summary>
|
||||
/// 请求ID,用于匹配回调
|
||||
/// </summary>
|
||||
public string requestId;
|
||||
|
||||
/// <summary>
|
||||
/// API名称,如 "showToast", "login" 等
|
||||
/// </summary>
|
||||
public string api;
|
||||
|
||||
/// <summary>
|
||||
/// API参数,JSON格式
|
||||
/// </summary>
|
||||
public string data;
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳
|
||||
/// </summary>
|
||||
public long timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PC高性能方案通信协议 - 响应消息
|
||||
/// 基础库 -> 内核 -> DLL -> C#
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPResponseMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息类型: "response" | "event"
|
||||
/// </summary>
|
||||
public string type;
|
||||
|
||||
/// <summary>
|
||||
/// 请求ID,与请求消息匹配
|
||||
/// </summary>
|
||||
public string requestId;
|
||||
|
||||
/// <summary>
|
||||
/// 回调类型: "success" | "fail" | "complete"
|
||||
/// </summary>
|
||||
public string callbackType;
|
||||
|
||||
/// <summary>
|
||||
/// API名称(事件类型时使用)
|
||||
/// </summary>
|
||||
public string api;
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据,JSON格式
|
||||
/// </summary>
|
||||
public string data;
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息(失败时)
|
||||
/// </summary>
|
||||
public string errMsg;
|
||||
|
||||
/// <summary>
|
||||
/// 时间戳
|
||||
/// </summary>
|
||||
public long timestamp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通用回调结果
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPGeneralCallbackResult
|
||||
{
|
||||
public string errMsg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ShowToast 参数
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPShowToastOption
|
||||
{
|
||||
public string title;
|
||||
public string icon;
|
||||
public string image;
|
||||
public int duration;
|
||||
public bool mask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ShowModal 参数
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPShowModalOption
|
||||
{
|
||||
public string title;
|
||||
public string content;
|
||||
public bool showCancel;
|
||||
public string cancelText;
|
||||
public string cancelColor;
|
||||
public string confirmText;
|
||||
public string confirmColor;
|
||||
public bool editable;
|
||||
public string placeholderText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ShowModal 成功回调结果
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class PCHPShowModalSuccessCallbackResult
|
||||
{
|
||||
public bool confirm;
|
||||
public bool cancel;
|
||||
public string content;
|
||||
public string errMsg;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// PC高性能小游戏初始化脚本
|
||||
/// 负责与宿主程序的 direct_applet_sdk.dll 进行交互
|
||||
/// </summary>
|
||||
public class WXPCHPInitScript : MonoBehaviour
|
||||
{
|
||||
#region DLL Imports
|
||||
|
||||
private const string DLL_NAME = "direct_applet_sdk.dll";
|
||||
|
||||
// 初始化SDK
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool InitEmbeddedGameSDK();
|
||||
|
||||
// 注册异步消息处理器
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void RegisterAsyncMsgHandler(AsyncMsgHandlerDelegate handler);
|
||||
|
||||
// 建立Mojo连接
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool EstablishConnection();
|
||||
|
||||
// 初始化游戏窗口 - 传入窗口句柄
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool InitGameWindow(ulong hwnd);
|
||||
|
||||
// 异步发送消息
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool SendMsgAsync(IntPtr data, int len);
|
||||
|
||||
// 清理资源
|
||||
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern bool Cleanup();
|
||||
|
||||
// 获取当前活动窗口句柄
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetActiveWindow();
|
||||
|
||||
// Windows MessageBox
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delegate Definition
|
||||
|
||||
// 异步消息处理器委托
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void AsyncMsgHandlerDelegate(IntPtr data, int len);
|
||||
|
||||
// 保持委托引用,防止被GC回收
|
||||
private static AsyncMsgHandlerDelegate asyncMsgHandler;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Singleton
|
||||
|
||||
private static WXPCHPInitScript instance;
|
||||
public static WXPCHPInitScript Instance => instance;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Callback Management
|
||||
|
||||
/// <summary>
|
||||
/// 回调信息封装
|
||||
/// </summary>
|
||||
private class CallbackInfo
|
||||
{
|
||||
public Action<string> OnSuccess;
|
||||
public Action<string> OnFail;
|
||||
public Action<string> OnComplete;
|
||||
public string ApiName;
|
||||
public long Timestamp;
|
||||
}
|
||||
|
||||
// 待处理的回调字典 <requestId, CallbackInfo>
|
||||
private readonly Dictionary<string, CallbackInfo> _pendingCallbacks = new Dictionary<string, CallbackInfo>();
|
||||
|
||||
// 事件监听器字典 <eventName, List<Action<string>>>
|
||||
private readonly Dictionary<string, List<Action<string>>> _eventListeners = new Dictionary<string, List<Action<string>>>();
|
||||
|
||||
// 请求ID计数器
|
||||
private int _requestIdCounter = 0;
|
||||
|
||||
// 线程安全的消息队列,用于主线程处理
|
||||
private readonly ConcurrentQueue<PCHPResponseMessage> _messageQueue = new ConcurrentQueue<PCHPResponseMessage>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
// 收到异步消息时触发的事件(原始字节)
|
||||
public event Action<byte[]> OnMessageReceived;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
// SDK是否已初始化
|
||||
public bool IsInitialized { get; private set; }
|
||||
|
||||
// 是否已连接
|
||||
public bool IsConnected { get; private set; }
|
||||
|
||||
// 窗口句柄
|
||||
public IntPtr WindowHandle { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unity Lifecycle
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Debug.Log("[WXPCHPInitScript] ========== Awake 被调用 ==========");
|
||||
Debug.Log($"[WXPCHPInitScript] GameObject 名称: {gameObject.name}");
|
||||
Debug.Log($"[WXPCHPInitScript] 场景名称: {UnityEngine.SceneManagement.SceneManager.GetActiveScene().name}");
|
||||
|
||||
if (instance != null && instance != this)
|
||||
{
|
||||
Debug.LogWarning("[WXPCHPInitScript] 检测到重复实例,销毁当前对象");
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
Debug.Log("[WXPCHPInitScript] 单例创建成功,已设置 DontDestroyOnLoad");
|
||||
|
||||
// 初始化SDK
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 在主线程中处理消息队列
|
||||
ProcessMessageQueue();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (instance == this)
|
||||
{
|
||||
CleanupSDK();
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
CleanupSDK();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods - SDK Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// 初始化SDK并建立连接
|
||||
/// </summary>
|
||||
public void Initialize()
|
||||
{
|
||||
if (IsInitialized)
|
||||
{
|
||||
Debug.LogWarning("[WXPCHPInitScript] SDK已经初始化");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("[WXPCHPInitScript] ========== 开始初始化 ==========");
|
||||
Debug.Log($"[WXPCHPInitScript] 当前工作目录: {System.IO.Directory.GetCurrentDirectory()}");
|
||||
Debug.Log($"[WXPCHPInitScript] DLL 搜索路径: {DLL_NAME}");
|
||||
|
||||
ShowStepInfo("SDK 初始化开始", "即将执行 PC 高性能模式 SDK 初始化流程...\n\n共 5 个步骤:\n1. InitEmbeddedGameSDK\n2. RegisterAsyncMsgHandler\n3. EstablishConnection\n4. GetActiveWindow\n5. InitGameWindow");
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 初始化SDK
|
||||
Debug.Log("[WXPCHPInitScript] Step 1: 调用 InitEmbeddedGameSDK");
|
||||
ShowStepInfo("步骤 1/5 - InitEmbeddedGameSDK", "正在初始化嵌入式游戏 SDK...");
|
||||
if (!InitEmbeddedGameSDK())
|
||||
{
|
||||
ShowError("InitEmbeddedGameSDK 返回 false");
|
||||
return;
|
||||
}
|
||||
ShowStepInfo("步骤 1/5 - InitEmbeddedGameSDK ✅", "InitEmbeddedGameSDK 调用成功!");
|
||||
|
||||
// 2. 注册消息处理器
|
||||
Debug.Log("[WXPCHPInitScript] Step 2: 调用 RegisterAsyncMsgHandler");
|
||||
ShowStepInfo("步骤 2/5 - RegisterAsyncMsgHandler", "正在注册异步消息处理器...");
|
||||
asyncMsgHandler = HandleAsyncMessage;
|
||||
RegisterAsyncMsgHandler(asyncMsgHandler);
|
||||
ShowStepInfo("步骤 2/5 - RegisterAsyncMsgHandler ✅", "异步消息处理器注册成功!");
|
||||
|
||||
// 3. 建立连接
|
||||
Debug.Log("[WXPCHPInitScript] Step 3: 调用 EstablishConnection");
|
||||
ShowStepInfo("步骤 3/5 - EstablishConnection", "正在建立 Mojo 连接...");
|
||||
if (!EstablishConnection())
|
||||
{
|
||||
ShowError("EstablishConnection 返回 false");
|
||||
IsConnected = false;
|
||||
return;
|
||||
}
|
||||
IsConnected = true;
|
||||
ShowStepInfo("步骤 3/5 - EstablishConnection ✅", "Mojo 连接建立成功!");
|
||||
|
||||
// 4. 获取窗口句柄并初始化游戏窗口
|
||||
Debug.Log("[WXPCHPInitScript] Step 4: 获取窗口句柄");
|
||||
ShowStepInfo("步骤 4/5 - GetActiveWindow", "正在获取游戏窗口句柄...");
|
||||
WindowHandle = GetActiveWindow();
|
||||
if (WindowHandle == IntPtr.Zero)
|
||||
{
|
||||
ShowError("GetActiveWindow 返回空句柄");
|
||||
return;
|
||||
}
|
||||
Debug.Log($"获取窗口句柄成功: 0x{WindowHandle.ToInt64():X}");
|
||||
ShowStepInfo("步骤 4/5 - GetActiveWindow ✅", $"窗口句柄获取成功: 0x{WindowHandle.ToInt64():X}");
|
||||
|
||||
// 5. 通知内核获取窗口句柄
|
||||
Debug.Log("[WXPCHPInitScript] Step 5: 调用 InitGameWindow");
|
||||
ShowStepInfo("步骤 5/5 - InitGameWindow", $"正在初始化游戏窗口...\n窗口句柄: 0x{WindowHandle.ToInt64():X}");
|
||||
if (!InitGameWindow((ulong)WindowHandle.ToInt64()))
|
||||
{
|
||||
ShowError("InitGameWindow 返回 false");
|
||||
return;
|
||||
}
|
||||
ShowStepInfo("步骤 5/5 - InitGameWindow ✅", "游戏窗口初始化成功!");
|
||||
|
||||
IsInitialized = true;
|
||||
Debug.Log("[WXPCHPInitScript] ========== 初始化完成 ==========");
|
||||
ShowStepInfo("🎉 SDK 初始化完成", "PC 高性能模式 SDK 所有步骤均已成功完成!\n\n✅ InitEmbeddedGameSDK\n✅ RegisterAsyncMsgHandler\n✅ EstablishConnection\n✅ GetActiveWindow\n✅ InitGameWindow");
|
||||
}
|
||||
catch (DllNotFoundException e)
|
||||
{
|
||||
ShowError($"找不到DLL: {e.Message}\n\n请确保 {DLL_NAME} 在以下位置之一:\n- 与 .exe 同级目录\n- System32 目录\n- PATH 环境变量包含的路径");
|
||||
Debug.LogError($"[WXPCHPInitScript] DLL 加载失败,请确保 {DLL_NAME} 在以下位置之一:");
|
||||
Debug.LogError($" - 与 .exe 同级目录");
|
||||
Debug.LogError($" - System32 目录");
|
||||
Debug.LogError($" - PATH 环境变量包含的路径");
|
||||
}
|
||||
catch (EntryPointNotFoundException e)
|
||||
{
|
||||
ShowError($"找不到函数入口: {e.Message}\n\n可能是 DLL 版本不匹配");
|
||||
Debug.LogError($"[WXPCHPInitScript] 函数入口点错误,可能是 DLL 版本不匹配");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ShowError($"初始化异常: {e.Message}\n{e.StackTrace}");
|
||||
Debug.LogError($"[WXPCHPInitScript] 未知异常: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods - WX API Calls
|
||||
|
||||
/// <summary>
|
||||
/// 调用微信API(通用方法)
|
||||
/// </summary>
|
||||
/// <param name="apiName">API名称,如 "showToast"</param>
|
||||
/// <param name="data">API参数对象</param>
|
||||
/// <param name="onSuccess">成功回调</param>
|
||||
/// <param name="onFail">失败回调</param>
|
||||
/// <param name="onComplete">完成回调</param>
|
||||
/// <returns>请求ID</returns>
|
||||
public string CallWXAPI(string apiName, object data, Action<string> onSuccess = null, Action<string> onFail = null, Action<string> onComplete = null)
|
||||
{
|
||||
if (!IsInitialized || !IsConnected)
|
||||
{
|
||||
Debug.LogWarning($"[WXPCHPInitScript] SDK未初始化或未连接,无法调用 {apiName}");
|
||||
onFail?.Invoke(JsonMapper.ToJson(new PCHPGeneralCallbackResult { errMsg = "SDK not initialized" }));
|
||||
onComplete?.Invoke(JsonMapper.ToJson(new PCHPGeneralCallbackResult { errMsg = "SDK not initialized" }));
|
||||
return null;
|
||||
}
|
||||
|
||||
string requestId = GenerateRequestId();
|
||||
string dataJson = data != null ? JsonMapper.ToJson(data) : "{}";
|
||||
|
||||
// 注册回调
|
||||
var callbackInfo = new CallbackInfo
|
||||
{
|
||||
OnSuccess = onSuccess,
|
||||
OnFail = onFail,
|
||||
OnComplete = onComplete,
|
||||
ApiName = apiName,
|
||||
Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
};
|
||||
_pendingCallbacks[requestId] = callbackInfo;
|
||||
|
||||
// 构建请求消息
|
||||
var request = new PCHPRequestMessage
|
||||
{
|
||||
type = "request",
|
||||
requestId = requestId,
|
||||
api = apiName,
|
||||
data = dataJson,
|
||||
timestamp = callbackInfo.Timestamp
|
||||
};
|
||||
|
||||
string requestJson = JsonMapper.ToJson(request);
|
||||
Debug.Log($"[WXPCHPInitScript] 发送API请求: {apiName}, requestId: {requestId}");
|
||||
|
||||
if (!SendMessageInternal(requestJson))
|
||||
{
|
||||
_pendingCallbacks.Remove(requestId);
|
||||
onFail?.Invoke(JsonMapper.ToJson(new PCHPGeneralCallbackResult { errMsg = "Failed to send message" }));
|
||||
onComplete?.Invoke(JsonMapper.ToJson(new PCHPGeneralCallbackResult { errMsg = "Failed to send message" }));
|
||||
return null;
|
||||
}
|
||||
|
||||
return requestId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示消息提示框
|
||||
/// </summary>
|
||||
public void ShowToast(PCHPShowToastOption option, Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
CallWXAPI("showToast", option,
|
||||
res => success?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => fail?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => complete?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏消息提示框
|
||||
/// </summary>
|
||||
public void HideToast(Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
CallWXAPI("hideToast", null,
|
||||
res => success?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => fail?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => complete?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示模态对话框
|
||||
/// </summary>
|
||||
public void ShowModal(PCHPShowModalOption option, Action<PCHPShowModalSuccessCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
CallWXAPI("showModal", option,
|
||||
res => success?.Invoke(JsonMapper.ToObject<PCHPShowModalSuccessCallbackResult>(res)),
|
||||
res => fail?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => complete?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示 loading 提示框
|
||||
/// </summary>
|
||||
public void ShowLoading(string title, bool mask = false, Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
CallWXAPI("showLoading", new { title, mask },
|
||||
res => success?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => fail?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => complete?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏 loading 提示框
|
||||
/// </summary>
|
||||
public void HideLoading(Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
CallWXAPI("hideLoading", null,
|
||||
res => success?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => fail?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res)),
|
||||
res => complete?.Invoke(JsonMapper.ToObject<PCHPGeneralCallbackResult>(res))
|
||||
);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods - Event Listeners
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件监听器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称,如 "onShow", "onHide"</param>
|
||||
/// <param name="callback">回调函数</param>
|
||||
public void RegisterEventListener(string eventName, Action<string> callback)
|
||||
{
|
||||
if (!_eventListeners.ContainsKey(eventName))
|
||||
{
|
||||
_eventListeners[eventName] = new List<Action<string>>();
|
||||
|
||||
// 发送事件注册消息到基础库
|
||||
var request = new PCHPRequestMessage
|
||||
{
|
||||
type = "event_register",
|
||||
requestId = GenerateRequestId(),
|
||||
api = eventName,
|
||||
data = "{}",
|
||||
timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
};
|
||||
SendMessageInternal(JsonMapper.ToJson(request));
|
||||
}
|
||||
|
||||
_eventListeners[eventName].Add(callback);
|
||||
Debug.Log($"[WXPCHPInitScript] 注册事件监听: {eventName}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听器
|
||||
/// </summary>
|
||||
/// <param name="eventName">事件名称</param>
|
||||
/// <param name="callback">要移除的回调函数,为null则移除所有</param>
|
||||
public void UnregisterEventListener(string eventName, Action<string> callback = null)
|
||||
{
|
||||
if (!_eventListeners.ContainsKey(eventName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback == null)
|
||||
{
|
||||
_eventListeners.Remove(eventName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_eventListeners[eventName].Remove(callback);
|
||||
if (_eventListeners[eventName].Count == 0)
|
||||
{
|
||||
_eventListeners.Remove(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有监听器了,通知基础库取消注册
|
||||
if (!_eventListeners.ContainsKey(eventName))
|
||||
{
|
||||
var request = new PCHPRequestMessage
|
||||
{
|
||||
type = "event_unregister",
|
||||
requestId = GenerateRequestId(),
|
||||
api = eventName,
|
||||
data = "{}",
|
||||
timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
|
||||
};
|
||||
SendMessageInternal(JsonMapper.ToJson(request));
|
||||
}
|
||||
|
||||
Debug.Log($"[WXPCHPInitScript] 移除事件监听: {eventName}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods - Raw Message
|
||||
|
||||
/// <summary>
|
||||
/// 发送原始消息字符串
|
||||
/// </summary>
|
||||
/// <param name="message">消息内容</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public bool SendRawMessage(string message)
|
||||
{
|
||||
return SendMessageInternal(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送原始消息字节数组
|
||||
/// </summary>
|
||||
/// <param name="data">消息数据</param>
|
||||
/// <returns>是否发送成功</returns>
|
||||
public bool SendMessage(byte[] data)
|
||||
{
|
||||
if (!IsInitialized || !IsConnected)
|
||||
{
|
||||
Debug.LogWarning("[WXPCHPInitScript] SDK未初始化或未连接");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == null || data.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("[WXPCHPInitScript] 发送的数据为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
IntPtr ptr = Marshal.AllocHGlobal(data.Length);
|
||||
try
|
||||
{
|
||||
Marshal.Copy(data, 0, ptr, data.Length);
|
||||
return SendMsgAsync(ptr, data.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 发送消息异常: {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// 生成唯一请求ID
|
||||
/// </summary>
|
||||
private string GenerateRequestId()
|
||||
{
|
||||
return $"pchp_{++_requestIdCounter}_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 内部发送消息方法
|
||||
/// </summary>
|
||||
private bool SendMessageInternal(string message)
|
||||
{
|
||||
if (!IsInitialized || !IsConnected)
|
||||
{
|
||||
Debug.LogWarning("[WXPCHPInitScript] SDK未初始化或未连接");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
|
||||
return SendMessage(data);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 发送消息异常: {e.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示步骤信息弹窗(Windows 使用 MessageBox,其他平台使用 Debug.Log)
|
||||
/// </summary>
|
||||
private void ShowStepInfo(string title, string message)
|
||||
{
|
||||
Debug.Log($"[WXPCHPInitScript] [{title}] {message}");
|
||||
#if UNITY_STANDALONE_WIN
|
||||
try
|
||||
{
|
||||
// MB_OK | MB_ICONINFORMATION = 0x40
|
||||
MessageBox(IntPtr.Zero, message, $"PC高性能模式 - {title}", 0x40);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[WXPCHPInitScript] MessageBox 调用失败: {e.Message}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示错误弹窗(仅 Windows)
|
||||
/// </summary>
|
||||
private void ShowError(string message)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] {message}");
|
||||
#if UNITY_STANDALONE_WIN
|
||||
try
|
||||
{
|
||||
// MB_OK | MB_ICONERROR = 0x10
|
||||
MessageBox(IntPtr.Zero, message, "WXPCHPInitScript Error", 0x10);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning($"[WXPCHPInitScript] MessageBox 调用失败: {e.Message}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理SDK资源
|
||||
/// </summary>
|
||||
private void CleanupSDK()
|
||||
{
|
||||
if (!IsInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 清理待处理回调
|
||||
_pendingCallbacks.Clear();
|
||||
_eventListeners.Clear();
|
||||
|
||||
Cleanup();
|
||||
Debug.Log("[WXPCHPInitScript] SDK清理完成");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 清理异常: {e.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsInitialized = false;
|
||||
IsConnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在主线程中处理消息队列
|
||||
/// </summary>
|
||||
private void ProcessMessageQueue()
|
||||
{
|
||||
while (_messageQueue.TryDequeue(out var response))
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessResponse(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 处理响应消息异常: {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理响应消息
|
||||
/// </summary>
|
||||
private void ProcessResponse(PCHPResponseMessage response)
|
||||
{
|
||||
if (response.type == "response")
|
||||
{
|
||||
// 处理API回调
|
||||
if (_pendingCallbacks.TryGetValue(response.requestId, out var callbackInfo))
|
||||
{
|
||||
Debug.Log($"[WXPCHPInitScript] 收到API响应: {callbackInfo.ApiName}, callbackType: {response.callbackType}");
|
||||
|
||||
switch (response.callbackType)
|
||||
{
|
||||
case "success":
|
||||
callbackInfo.OnSuccess?.Invoke(response.data ?? "{}");
|
||||
break;
|
||||
case "fail":
|
||||
callbackInfo.OnFail?.Invoke(response.data ?? $"{{\"errMsg\":\"{response.errMsg}\"}}");
|
||||
break;
|
||||
case "complete":
|
||||
callbackInfo.OnComplete?.Invoke(response.data ?? "{}");
|
||||
// complete 后移除回调
|
||||
_pendingCallbacks.Remove(response.requestId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[WXPCHPInitScript] 未找到对应的回调: requestId={response.requestId}");
|
||||
}
|
||||
}
|
||||
else if (response.type == "event")
|
||||
{
|
||||
// 处理事件通知
|
||||
string eventName = response.api;
|
||||
if (_eventListeners.TryGetValue(eventName, out var listeners))
|
||||
{
|
||||
Debug.Log($"[WXPCHPInitScript] 收到事件: {eventName}");
|
||||
foreach (var listener in listeners.ToArray())
|
||||
{
|
||||
try
|
||||
{
|
||||
listener?.Invoke(response.data ?? "{}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 事件回调异常: {eventName}, {e.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步消息处理回调(从DLL回调,可能在非主线程)
|
||||
/// </summary>
|
||||
[AOT.MonoPInvokeCallback(typeof(AsyncMsgHandlerDelegate))]
|
||||
private static void HandleAsyncMessage(IntPtr data, int len)
|
||||
{
|
||||
if (data == IntPtr.Zero || len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[len];
|
||||
Marshal.Copy(data, buffer, 0, len);
|
||||
|
||||
if (instance != null)
|
||||
{
|
||||
// 触发原始消息事件
|
||||
instance.OnMessageReceived?.Invoke(buffer);
|
||||
|
||||
// 解析消息
|
||||
string message = System.Text.Encoding.UTF8.GetString(buffer);
|
||||
Debug.Log($"[WXPCHPInitScript] 收到原始消息: {message}");
|
||||
|
||||
try
|
||||
{
|
||||
// 尝试解析为响应消息
|
||||
var response = JsonMapper.ToObject<PCHPResponseMessage>(message);
|
||||
if (response != null && !string.IsNullOrEmpty(response.type))
|
||||
{
|
||||
// 加入消息队列,在主线程中处理
|
||||
instance._messageQueue.Enqueue(response);
|
||||
}
|
||||
}
|
||||
catch (Exception parseEx)
|
||||
{
|
||||
Debug.LogWarning($"[WXPCHPInitScript] 消息解析失败,可能是非标准格式: {parseEx.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"[WXPCHPInitScript] 处理消息异常: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PC高性能小游戏管理器
|
||||
/// 提供类似 wx.getPCHighPerformanceManager() 的接口
|
||||
/// </summary>
|
||||
public class WXPCHighPerformanceManager
|
||||
{
|
||||
private static WXPCHighPerformanceManager _instance;
|
||||
private WXPCHPInitScript _initScript;
|
||||
|
||||
/// <summary>
|
||||
/// 获取 PC 高性能管理器实例
|
||||
/// </summary>
|
||||
public static WXPCHighPerformanceManager GetInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new WXPCHighPerformanceManager();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private WXPCHighPerformanceManager()
|
||||
{
|
||||
_initScript = WXPCHPInitScript.Instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持PC高性能模式
|
||||
/// </summary>
|
||||
public bool IsSupported => _initScript != null && _initScript.IsInitialized && _initScript.IsConnected;
|
||||
|
||||
/// <summary>
|
||||
/// 调用微信API
|
||||
/// </summary>
|
||||
public string CallWXAPI(string apiName, object data, Action<string> onSuccess = null, Action<string> onFail = null, Action<string> onComplete = null)
|
||||
{
|
||||
if (_initScript == null)
|
||||
{
|
||||
Debug.LogError("[WXPCHighPerformanceManager] InitScript 未初始化");
|
||||
return null;
|
||||
}
|
||||
return _initScript.CallWXAPI(apiName, data, onSuccess, onFail, onComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示 Toast
|
||||
/// </summary>
|
||||
public void ShowToast(PCHPShowToastOption option, Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
_initScript?.ShowToast(option, success, fail, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏 Toast
|
||||
/// </summary>
|
||||
public void HideToast(Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
_initScript?.HideToast(success, fail, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示模态对话框
|
||||
/// </summary>
|
||||
public void ShowModal(PCHPShowModalOption option, Action<PCHPShowModalSuccessCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
_initScript?.ShowModal(option, success, fail, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示 Loading
|
||||
/// </summary>
|
||||
public void ShowLoading(string title, bool mask = false, Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
_initScript?.ShowLoading(title, mask, success, fail, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 隐藏 Loading
|
||||
/// </summary>
|
||||
public void HideLoading(Action<PCHPGeneralCallbackResult> success = null, Action<PCHPGeneralCallbackResult> fail = null, Action<PCHPGeneralCallbackResult> complete = null)
|
||||
{
|
||||
_initScript?.HideLoading(success, fail, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册事件监听
|
||||
/// </summary>
|
||||
public void On(string eventName, Action<string> callback)
|
||||
{
|
||||
_initScript?.RegisterEventListener(eventName, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除事件监听
|
||||
/// </summary>
|
||||
public void Off(string eventName, Action<string> callback = null)
|
||||
{
|
||||
_initScript?.UnregisterEventListener(eventName, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送原始消息
|
||||
/// </summary>
|
||||
public bool SendRawMessage(string message)
|
||||
{
|
||||
return _initScript?.SendRawMessage(message) ?? false;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Runtime/WXPCHPInitScript.cs.meta
Normal file
7
Runtime/WXPCHPInitScript.cs.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65b48177033749bf973a8af5bfb6b257
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3d5d2167fc6b91f7fa3e08ea84c3cda
|
||||
guid: 4d94f319aa622b03849c8e69a8c7cba9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c06693e00be3ab1fde2607590ab4e6d
|
||||
guid: d2fcde627429d4818f85e18d2a1263f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a02513af1cc852341848d1ee2622c3aa
|
||||
guid: b2af85219bfaf6a05bd3bd6bc6d03829
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de11e750d070e1521430f1ea7d7e9b10
|
||||
guid: bdf3bca45f7097b129e204847282cd24
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75c495849e8b58894c4df4019c28990f
|
||||
guid: 82604dd9fc856ac2a8ba9c065b3f0f74
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2676c806e8720f27b3c91d7b88934aea
|
||||
guid: 848a462a23628985852dc620380dc698
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f98ab3c051a738848f5f25b3963ff875
|
||||
guid: 1cd8e103dc8cb7c406056cbc19a0da7e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14b4dacf147a2eb0b690def4fd2a25f8
|
||||
guid: 6852f18e86c0b0f9d687cd12e757be11
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdc5a07bfe255668c4bc90b063ab0439
|
||||
guid: 92e78cafb9ee3bb507bb5f1d2d464323
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc12ac5f1dcfb4041e5b88bdb3d39df1
|
||||
guid: 6f8a3fb7d545a9c2f4cb6d3c911e01f8
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a78826b373fd69d30b14736655164fc
|
||||
guid: 900b8f09ecdfa2e72a70b84c1eebb774
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e3a00c4051da2b6217cd8e156b32adc
|
||||
guid: 6755f00877ecd893631231910933d4ed
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa4490b63d04c3666e7d5bd6dbbe4a58
|
||||
guid: 27270731c7e1bdae791f9a891df08bca
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 942f7b8a85c48dce854289ad244f3ca4
|
||||
guid: 05dff728b56a6788b0002a35db638ab3
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4dadbfddf470bde3a646527500a79bb6
|
||||
guid: 94baa1b07b72979942f824d3fa4316b8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1516197a3756cc06853320f648bd30f2
|
||||
guid: 33aecb9421d7577bff6a9cee399fc62f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b193152a2bbc37d0feda3c6544e7afc8
|
||||
guid: c09a5b303d2369195c430976d5111957
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5a694336b7dd91fd242250f890f19b5
|
||||
guid: 94afe4cf34619ee7284672597deadbdb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f862d1c69deabf4048bebed751c846d
|
||||
guid: f9f0235dd51f1b0c9efca63315546955
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7eb49c157fec3510cca59918268546d6
|
||||
guid: b7d881fe3f7853c0fc3b0372496327ec
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f6eb3ae66cc21f0114a7c9e15ac57d76
|
||||
guid: 85bc5ab7146f11bd3745c05213267810
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1151cf42fe9e3fe2b444ddddbde08396
|
||||
guid: c63d44cff96fed99b29285d650215e5b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b6db07c37dc2366237d59d8f785fd48
|
||||
guid: 748964f432130d20018c31e8ccf94765
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e2b29c063f2d000be5dd2313958fa6c
|
||||
guid: 669b1053fadcb602f4808ba75e5cb3eb
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d34cf0ce316d07409a850c605540a013
|
||||
guid: 132bf65501259226e755ef658860ce7c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d91ef4c43c9f3c9a6da9a65b379b5740
|
||||
guid: f2e77f03fa4132105e406e7b4e920986
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6660a6a8aacee1f2096340441fdbd3ce
|
||||
guid: cfd0447c19143ba4c424d510171c4749
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 119c8bb6b0ad127ed8bac3162a9969f8
|
||||
guid: de5d6956a4f8c950b00f2975a06c31b8
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59d869d78f133094896b88faa762234a
|
||||
guid: 4cd850965eb65ecb2add3c82a65c7636
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34d39008817c30ca826af31fc01525e7
|
||||
guid: 3b95c88fdcefc84eff7698ef331072d5
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73a18f6a646fbaf0e8526fc1526ae97a
|
||||
guid: 1599136c65ba399a0736ed477cd3f9be
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9e4678df01d9876b1b0aa336ee45401
|
||||
guid: 465f79e042f08f54238942e70a8ed88e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2c849f6ee1aeeb7f9ccc36695a38d24
|
||||
guid: cce28cd7abeb995a7ba56195e81169ba
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2200a16cb9b949081f51aa4fe6807bd
|
||||
guid: 5359d80250e657a8a992b76900a885f9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b89e0228f0375beca9b6d7b1ad95356a
|
||||
guid: b79c7144b7ef9c8be6c4acb2a21c1c1d
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c82e223e59fd93811d3aa303bb51f02e
|
||||
guid: d07f88297badc254af33d46394906cda
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c570e4eb7ff538d7aa640fb8c3d02da
|
||||
guid: dd6f9000617f9b2eca85bc6d599f1dd9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a8702f6acee306755d112480d39813c
|
||||
guid: f6327ad840f6a9069dd66ae83074db0b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90a536e2c5a0814cc1c58b70c92da9a4
|
||||
guid: b7bf48e81d891374a332b739fd1c40f7
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02830b8246e010bdd89e47fefd9adf6b
|
||||
guid: 741288a35af3a4b2c223537a51b417a6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 853f4640fa1b8a092c4ccb4669d6971c
|
||||
guid: 80c89ead5349646ae66ee700308752a5
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24c205c5759ec41da1b00eda2ac42564
|
||||
guid: b1460f620a984af813434501139116dc
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9782628a70978396e495b86274aa398d
|
||||
guid: 76b847977e20e6da3636dbc85053ad63
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 674bba89e7bc0b330d4920c8a1d2470f
|
||||
guid: 4c6345b052ef553a44d6ac3caa7f728b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: faa496c26f840b60f61ac89b5f564f32
|
||||
guid: 0fca09d72894fe57b36058f861fc0358
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cbac21da9894d5092f47042e7dcab8e
|
||||
guid: 21ce6c9ad9c1f25f1edabfca8fdd815e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa534e5bd9009a4f986abd6cc2ff823b
|
||||
guid: 02d787436f30a761a6576c6ac6342009
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3251c8f50cca5fae20e0e2bbc567bf40
|
||||
guid: fc7566ad1398845fc6a2e47416b0d8a8
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ee130afc0339063c59da8a830c7663e
|
||||
guid: baa810234733b35571eae2421bbf9827
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30161526e5960c70e6965463a8c98492
|
||||
guid: 6d4e09752bc145ec949170babf1e3ad6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47d2bb9aac0b87cfdf12358dc192e755
|
||||
guid: 6776648588f5283cef236aab3010cc97
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7babfccd3322d8f0bb49bb466cc03624
|
||||
guid: d3bf5af8a6c0a24dbe3f005cae269b3f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a99dd0e69496ec987fc46d387fee8587
|
||||
guid: 57fd82a56e3a9dba280254cacafb06c1
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: deb969752e56efd1f30292483076fe8d
|
||||
guid: edf0a9a1546e0e70e1d8f3ccf6ce3f83
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 873c3ff5c09c499cea533e76613b289c
|
||||
guid: dae4cb4ecc6068f06c542ff84c6bd0e7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b62dfcd3bba0143fe64bb393b6718200
|
||||
guid: 2c0452e405b404a968d147b3853d9427
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f5d268ad00ae324c34a888a2bc0f3b9
|
||||
guid: 9fb16bd225561e6021d61508ac89f731
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4b7634dc3628a25ae87b92a174f5056
|
||||
guid: e9b49edc671d3713d68f76cca4583f2b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acc81d1c264bc0dadd4552d59e6b5cc0
|
||||
guid: 4e16ff1a8624dff18d20295a4e8d4441
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 304fa8442a722ea29aaf75c80ecf36d0
|
||||
guid: 753e849f445689c7a3b964b271405451
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07577f5e35b0d9d10be3e7da2f636244
|
||||
guid: 58e440fe59f49a8b4d50db4b4d66803c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90f5231878ca8f4be00b3ce66b678dd1
|
||||
guid: c3cee16857cb4ecf47b34993780c7854
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f54994eb4369a71edd1d509002ad2f14
|
||||
guid: 19fdc70a4fb20e875bb2d97a0c593225
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48fbcdad3f9d3b9f921019659939b17c
|
||||
guid: 9795cee09e7fb8721ded3f3bc9731fd7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 116976e02bc785ec509b059f15a5826b
|
||||
guid: c1c2d57b345ad7106801b4a82839f91c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39b854a719f26a74ceafd3208b3d1559
|
||||
guid: 453707e476646856dd5bd0e66137166c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71c319aa5539d8cc938c59c1f95015a2
|
||||
guid: 272557131fc9049c4239ad3a9692462d
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c4cd8fe6d78dca85ddf042297dbfa8e
|
||||
guid: 9e4d2ace703f22091167280977581e33
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfe81ba23a1b4042745b051435b5580c
|
||||
guid: fd4d798f8f8c23f76172ae483a36cf71
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2047abd88a0e4c828645361f0825461
|
||||
guid: 21b143cea670ce892f9d285c056a6136
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05954e3656c1b42399214f7a474e1dc3
|
||||
guid: 33c723c5dfb6e5dd50ef97273ace5fc9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user