8.4 KiB
8.4 KiB
玩法编辑器系统 — 完整实现方案
系统架构
┌─────────────────────────────────────────────────────────────────┐
│ 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 包
# 在 Unity 项目中安装(需要配置 NuGet)
Install-Package EPPlus
API:
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
// 在某个 MonoBehaviour 中
public class GameplayController : MonoBehaviour
{
public Graph skillGraph;
public GraphDataSchema skillSchema;
private void Start()
{
var syncManager = gameObject.AddComponent<GraphExcelSyncManager>();
syncManager.targetGraph = skillGraph;
syncManager.schema = skillSchema;
}
}
第三步:编辑工作流
1. 在 Canvas 中编辑节点 → 自动同步到 Excel
2. 在 Excel 中修改数据 → 点击"同步 Excel → Canvas"更新
3. 支持批量编辑:在 Excel 中修改多行数据,一次性导入
数据流向示例
场景:编辑技能节点
Canvas 中的节点结构:
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. 节点类型过滤
schema.nodeTypeFilter = new List<string> { "SkillNode", "BuffNode" };
// 只同步这两种类型的节点
2. 嵌套字段支持
// 节点中有嵌套对象
public class SkillNode : FlowNode
{
public SkillData data;
}
public class SkillData
{
public float duration;
}
// Schema 配置支持嵌套路径
fieldName = "data.duration"
3. 自定义字段类型转换
// 在 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. 启用自动同步
// 在 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 中添加类型转换逻辑
扩展方向
- 支持多 Graph 同时编辑 → 在 GameplayEditorWindow 中添加 Tab 页
- 版本控制 → 记录每次同步的时间戳和变更内容
- 冲突解决 → 当 Canvas 和 Excel 同时修改时的合并策略
- 导出配置 → 将 Graph 导出为 JSON/Protobuf 供游戏运行时使用
- 可视化表格 → 在 Editor 中直接显示 Excel 表格,支持拖拽编辑