# 玩法编辑器系统 — 完整实现方案 ## 系统架构 ``` ┌─────────────────────────────────────────────────────────────────┐ │ GameplayEditorWindow (Editor) │ │ ┌──────────────────────────┐ ┌────────────────────────────┐ │ │ │ Canvas 可视化编辑 │ │ Excel 表格映射 │ │ │ │ (FlowCanvas/NodeCanvas) │ │ (GraphDataSchema) │ │ │ └──────────┬───────────────┘ └─────────────┬──────────────┘ │ │ │ │ │ │ └──────────────┬─────────────────┘ │ │ │ │ │ GraphExcelSyncManager (Runtime) │ │ (双向同步: Graph JSON ↔ Excel 表格) │ │ │ │ │ ┌──────────────────┴──────────────────┐ │ │ │ │ │ │ ExcelDataProvider Graph.onGraphSerialized │ │ (EPPlus 读写 .xlsx) (自动触发同步) │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 核心模块说明 ### 1. **GraphDataSchema** (`GraphDataSchema.cs`) 定义 Canvas 节点字段 ↔ Excel 列的映射关系 **使用方式:** ``` 在 Unity Editor 中: 1. 右键 → Create → GameplayEditor/GraphDataSchema 2. 配置字段映射: - fieldName: 节点中的字段名(支持嵌套如 'task.duration') - excelColumnName: Excel 表格列名 - fieldType: 数据类型(String/Int/Float/Bool/Vector3/Color) 3. 指定 sheetName(对应 Excel 中的 Sheet 名称) ``` **示例配置:** ``` Sheet: "技能" 字段映射: - ID → NodeID (Int) - name → NodeName (String) - comment → 描述 (String) - task.duration → 持续时间 (Float) ``` --- ### 2. **ExcelDataProvider** (`ExcelDataProvider.cs`) 负责读写 .xlsx 文件的底层操作 **依赖:** EPPlus NuGet 包 ```bash # 在 Unity 项目中安装(需要配置 NuGet) Install-Package EPPlus ``` **API:** ```csharp var provider = new ExcelDataProvider("Assets/玩法编辑器.xlsx"); // 读取 Sheet var data = provider.ReadSheet("技能"); // 写入 Sheet provider.WriteSheet("技能", nodeDataList); // 获取所有 Sheet 名称 var sheets = provider.GetSheetNames(); ``` --- ### 3. **GraphExcelSyncManager** (`GraphExcelSyncManager.cs`) 运行时双向同步管理器 **工作流程:** **Canvas → Excel(自动):** ``` Graph.SelfSerialize() ↓ (触发 onGraphSerialized 事件) ↓ GraphExcelSyncManager.OnGraphChanged() ↓ ExtractNodeData() (遍历所有节点,按 Schema 提取字段) ↓ ExcelDataProvider.WriteSheet() (写入 Excel) ``` **Excel → Canvas(手动触发):** ``` SyncExcelToGraph() ↓ ExcelDataProvider.ReadSheet() (读取 Excel 数据) ↓ ApplyDataToGraph() (按 NodeID 匹配节点,更新字段) ↓ Graph 节点更新完成 ``` --- ### 4. **GameplayEditorWindow** (`GameplayEditorWindow.cs`) 编辑器窗口 UI **打开方式:** `Window → Gameplay Editor` **功能:** - 左侧:Canvas 节点列表(实时显示) - 右侧:Schema 字段映射(配置参考) - 工具栏:同步按钮(Canvas ↔ Excel) --- ## 使用流程 ### 第一步:创建 Schema 配置 ``` 1. 在 Assets 中右键 → Create → GameplayEditor/GraphDataSchema 2. 命名为 "SkillGraphSchema" 3. 配置字段映射(对应你的 Graph 节点结构) 4. 保存 ``` ### 第二步:配置 SyncManager ```csharp // 在某个 MonoBehaviour 中 public class GameplayController : MonoBehaviour { public Graph skillGraph; public GraphDataSchema skillSchema; private void Start() { var syncManager = gameObject.AddComponent(); syncManager.targetGraph = skillGraph; syncManager.schema = skillSchema; } } ``` ### 第三步:编辑工作流 ``` 1. 在 Canvas 中编辑节点 → 自动同步到 Excel 2. 在 Excel 中修改数据 → 点击"同步 Excel → Canvas"更新 3. 支持批量编辑:在 Excel 中修改多行数据,一次性导入 ``` --- ## 数据流向示例 ### 场景:编辑技能节点 **Canvas 中的节点结构:** ```csharp public class SkillNode : FlowNode { public int skillID; public string skillName; public float cooldown; public int manaCost; } ``` **Schema 配置:** ``` Sheet: "技能" 字段映射: - skillID → 技能ID (Int) - skillName → 技能名称 (String) - cooldown → 冷却时间 (Float) - manaCost → 魔法消耗 (Int) ``` **Excel 表格:** ``` | 技能ID | 技能名称 | 冷却时间 | 魔法消耗 | |--------|---------|---------|---------| | 1 | 火球术 | 5.0 | 50 | | 2 | 冰冻术 | 8.0 | 60 | ``` **同步流程:** ``` 修改 Canvas 节点 → Graph.SelfSerialize() → onGraphSerialized 事件触发 → ExtractNodeData() 提取 [skillID, skillName, cooldown, manaCost] → WriteSheet() 写入 Excel → Excel 自动更新 ``` --- ## 高级特性 ### 1. 节点类型过滤 ```csharp schema.nodeTypeFilter = new List { "SkillNode", "BuffNode" }; // 只同步这两种类型的节点 ``` ### 2. 嵌套字段支持 ```csharp // 节点中有嵌套对象 public class SkillNode : FlowNode { public SkillData data; } public class SkillData { public float duration; } // Schema 配置支持嵌套路径 fieldName = "data.duration" ``` ### 3. 自定义字段类型转换 ```csharp // 在 ExcelDataProvider 中扩展 private object ConvertValue(object value, GraphDataSchema.FieldType type) { switch (type) { case GraphDataSchema.FieldType.Vector3: // 自定义 Vector3 解析逻辑 break; // ... } } ``` --- ## 集成现有项目的步骤 ### 1. 复制文件到项目 ``` Assets/BP_Scripts/GameplayEditor/ ├── GraphDataSchema.cs ├── ExcelDataProvider.cs ├── GraphExcelSyncManager.cs └── GameplayEditorWindow.cs ``` ### 2. 安装 EPPlus 依赖 ``` 在 Packages/manifest.json 中添加: "com.epplus": "https://github.com/EPPlusSoftware/EPPlus.git" ``` ### 3. 为现有 Graph 创建 Schema ``` 对于每个 Graph 类型(技能、关卡、单位、行为树), 创建对应的 Schema 配置文件 ``` ### 4. 启用自动同步 ```csharp // 在 GameplayController 中 private void OnEnable() { Graph.onGraphSerialized += OnGraphChanged; } ``` --- ## 与参考项目的对应关系 | 参考项目文件 | 我们的实现 | 用途 | |---|---|---| | `行为树教程.xlsx` | `GraphDataSchema` | 定义表格结构 | | `x效果C054.xlsm` | `ExcelDataProvider` | 读写 Excel | | `g关卡C036.xlsm` | `GameplayEditorWindow` | 编辑界面 | | `d单位G071.xlsm` | `GraphExcelSyncManager` | 数据同步 | --- ## 故障排查 ### 问题 1:Excel 文件被锁定 **原因:** 文件被其他程序打开 **解决:** 关闭 Excel,重新同步 ### 问题 2:字段映射不生效 **原因:** fieldName 拼写错误或字段不存在 **解决:** 检查 Schema 配置中的 fieldName 是否与节点字段名完全匹配 ### 问题 3:数据类型转换失败 **原因:** Excel 中的数据类型与 Schema 定义不符 **解决:** 在 ExcelDataProvider 中添加类型转换逻辑 --- ## 扩展方向 1. **支持多 Graph 同时编辑** → 在 GameplayEditorWindow 中添加 Tab 页 2. **版本控制** → 记录每次同步的时间戳和变更内容 3. **冲突解决** → 当 Canvas 和 Excel 同时修改时的合并策略 4. **导出配置** → 将 Graph 导出为 JSON/Protobuf 供游戏运行时使用 5. **可视化表格** → 在 Editor 中直接显示 Excel 表格,支持拖拽编辑