11 KiB
11 KiB
载具科技树生成 功能说明
一、功能概述
载具科技树生成是一个 Unity 编辑器工具,用于根据配置表数据自动构建载具科技树和组件(部件)树的 UI 预制体。生成的预制体供运行时 UI 界面加载使用。
编辑器菜单入口:Tools / *UI / 载具科技树生成
二、核心文件一览
编辑器侧
| 文件路径 | 类名 | 职责 |
|---|---|---|
Assets/EditorHelper/AreaEditor/TreeEditor/TreeEditorWindow.cs |
TreeEditorWindow |
Odin 编辑器窗口,提供派系/载具选择菜单 |
Assets/EditorHelper/AreaEditor/TreeEditor/TreeEditPreload.cs |
TreeEditPreload |
预加载器,加载配置表、打开编辑场景、触发树生成 |
Assets/EditorHelper/AreaEditor/TreeEditor/VehicleTreeManager.cs |
VehicleTreeManager |
核心管理器,负责树数据构建、节点创建、布局计算、连线绘制 |
Assets/EditorHelper/AreaEditor/TreeEditor/TreeEditorManager.cs |
TreeEditorManager |
抽象基类,提供分层树 / 非分层树的通用布局算法 |
Assets/EditorHelper/AreaEditor/TreeEditor/Editor/VehicleTreeManagerEditor.cs |
VehicleTreeManagerEditor |
自定义 Inspector,提供"重新生成连线"和"保存为预制体"按钮 |
Assets/EditorHelper/AreaEditor/TreeEditor/Node.cs |
Node / TreeData |
节点数据类(NodeId、父子关系、深度、对应 GameObject) |
Assets/EditorHelper/AreaEditor/TreeEditor/TileManager.cs |
TileManager |
管理节点 UI 模板预制体列表,按索引实例化 |
Assets/EditorHelper/AreaEditor/TreeEditor/LineDrawer.cs |
LineDrawer |
连线绘制辅助 |
Assets/EditorHelper/AreaEditor/TreeEditor/PloegTreeLayout.cs |
PloegTreeLayout |
Ploeg 布局算法(非分层树使用) |
Assets/EditorHelper/AreaEditor/TreeEditor/Reingold-Tilford/TreeHelpers.cs |
TreeHelpers |
Reingold-Tilford 布局算法(分层树使用) |
Assets/EditorHelper/AreaEditor/TreeEditor/Reingold-Tilford/TreeNodeModel.cs |
TreeNodeModel |
布局算法的树节点模型 |
运行时侧
| 文件路径 | 类名 | 职责 |
|---|---|---|
Assets/Code/Scripts/GamePlay/UI/VehicleCultivate/VehicleCultivateManager.cs |
VehicleCultivateManager |
运行时数据管理器,包含静态方法 LoadVehicleTreeNode 加载树节点数据(编辑器和运行时共用) |
Assets/Code/Scripts/GamePlay/UI/UI_VehicleTechTreeController.cs |
UI_VehicleTechTreeController |
运行时科技树 UI 控制器,管理派系切换、节点状态显示 |
三、两种树类型
VehicleTreeManager 通过枚举 TreeContent 区分两种树:
1. 载具树 (TreeContent.Vehicle)
- 作用:按派系(
VehicleType)展示所有载具的层级关系 - 布局算法:分层布局(
TreeType.layered),基于 Reingold-Tilford 算法 - 节点深度:由配置表中的
VehicleLevel决定(非自然树深度) - 特殊处理:
Buy类型载具按等级排序后串联成链
2. 组件树 / 部件树 (TreeContent.Component)
- 作用:展示某个载具下的子载具和子部件的树形结构
- 布局算法:非分层布局(
TreeType.non_layered),基于 Ploeg 算法 - 根节点:指定载具 ID 作为根
- 遍历方式:BFS 遍历根载具的
VehicleChildren和ComponentChildren - 额外调整:支持自定义根节点位置(
componentTreeRootPosition)和深层节点间距(deepNodeVerticalSpacing)
四、生成流程详解
4.1 总体调用链
TreeEditorWindow.OpenWindow() ← 菜单入口
└── 用户选择派系/载具后点击按钮
└── TreeEditPreload.OpenScene()
├── EditorTableManager.ForceReload() ← 加载配置表
├── EditorSceneManager.OpenScene(TreeEditorScene.unity) ← 打开编辑场景
└── VehicleTreeManager.ForceInit() ← 初始化并生成树
├── ClearCurrentTree() ← 清理旧数据
└── LoadOrInit()
├── VehicleCultivateManager.LoadVehicleTreeNode() ← 从配置表加载节点数据
└── TreeInit() ← 构建并布局树
4.2 TreeInit() 核心流程
TreeInit()
│
├── 1. CreateTree() ← 根据配置创建 Node 对象,建立父子关系
│ ├── [载具树] 循环遍历所有 VehicleTreeNode
│ │ ├── 创建 ID=0 的虚拟根节点
│ │ ├── 按父子依赖逐轮添加节点(while 循环直到无新节点)
│ │ ├── 对每个节点:判断 UnlockType 选择模板 → 设置图标/名称/类型标识
│ │ └── Buy 类型节点按 VehicleLevel 排序后重新串联父子关系
│ │
│ └── [组件树] BFS 遍历根载具的子节点
│ ├── 创建根载具节点
│ ├── 将 VehicleChildren 和 ComponentChildren 入队
│ ├── BFS 循环:创建节点、区分子载具/子部件选择不同模板
│ └── 设置图标、部件类型图标等属性
│
├── 2. CreatePrefab(treeGameObject) ← 将所有 Node.tile 挂载到树 GameObject 下
│ └── BFS 遍历所有节点,设置 parent、localScale、命名为 "v_{NodeId}"
│
├── 3. 布局计算
│ ├── [分层树 layered]
│ │ ├── GetSampleTree() ← 构建 TreeNodeModel 树结构
│ │ ├── TreeHelpers.CalculateNodePositions() ← Reingold-Tilford 算法计算 X/Y
│ │ └── PrintPos() ← 设置 RectTransform.anchoredPosition
│ │ └── 深度取自 VehicleLevel 而非自然树深度
│ │
│ └── [非分层树 non_layered]
│ ├── calculateDepth() ← BFS 计算各节点深度
│ ├── SetNonLayeredTreeLayout() ← 初步布局
│ ├── PloegLayout() ← Ploeg 算法精确布局
│ ├── AdjustDeepNodeSpacing() ← 深层节点额外间距调整
│ └── AdjustComponentTreePosition() ← 整体偏移使根节点到指定位置
│
└── 4. DrawLine(treeGameObject) ← 绘制连线
├── 创建/获取 LineParent 子对象上的 UILineRenderer
├── 遍历所有节点 → 遍历其 childrenIDs
│ ├── Buy→Buy 连线跳过
│ ├── 直线模式:起点→终点
│ └── 折线模式:起点→中间点1→中间点2→终点
└── lineRenderer.SetPoints(points) 提交连线数据
4.3 保存为预制体
通过 Inspector 上的按钮或 OnGUI 按钮触发:
PrefabUtility.SaveAsPrefabAsset(
m_shownTree,
"Assets/Art_Out/UI/Prefab/Interface_Vehicle/TechTree/" + m_shownTree.name + ".prefab"
);
- 载具树命名格式:
{VehicleType}_0.prefab - 组件树命名格式:
TechTree_{VehicleID}.prefab
五、使用的资源文件
5.1 编辑场景
| 资源 | 路径 |
|---|---|
| 编辑器场景 | Assets/Editor/UIEditor/TreeEditorScene.unity |
| 编辑器预制体 | Assets/EditorHelper/AreaEditor/TreeEditor/Editor/Vehicle_Editor_Prefab.prefab |
5.2 节点模板预制体(TileManager.TilePrefabs)
配置在 Vehicle_Editor_Prefab.prefab 的 TileManager 组件中,共 5 个模板:
| 索引 | Prefab 文件 | 用途 |
|---|---|---|
| 0 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/VehicleTechTreeList_VehicleItemRMB_New.prefab |
载具树 - Buy 类型载具节点 / 虚拟根节点 |
| 1 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/VehicleTechTreeList_VehicleItemNormal_New.prefab |
载具树 - 普通解锁类型载具节点 |
| 2 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/VehiclePartTreeList_PartItem_New.prefab |
组件树 - 子部件节点 |
| 3 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/VehiclePartTreeList_VehicleItem_New.prefab |
组件树 - 子载具节点 |
| 4 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/VehiclePartTreeList_VehicleItemRoot.prefab |
组件树 - 根节点(当前载具) |
5.3 图标资源
| 用途 | 路径模式 |
|---|---|
| 载具头像图标 | Assets/Art_Out/UI/Texture/Icon/Vehicle/NewHeadPic/{UIHeadPath} |
| 载具类型图标 | Assets/Art_Out/UI/Texture/Icon/Vehicle/VehicleType/{TypeIcon}.png |
| 部件图标 | Assets/Art_Out/UI/Texture/Icon/Vehicle/VehiclePart/{Icon} |
| 部件类型图标 | Assets/Art_Out/UI/Texture/Icon/Vehicle/VehiclePartType/{VehiclePartIcon}.png |
| 默认头像(隐藏载具) | Assets/Art_Out/UI/Texture/Icon/Vehicle/NewHeadPic/Icon_Vehicle_C00000.png |
5.4 配置表(数据源)
| 配置表 | 提供数据 |
|---|---|
VehicleConfig |
载具 ID、名称、派系类型、等级、解锁类型、图标路径、是否隐藏 |
VehicleComponent |
部件 ID、所属载具、部件类型、图标 |
ConditionConfig |
解锁条件(用于构建父子关系) |
GlobalConfig |
部件类型图标路径配置 |
5.5 生成产物(输出)
| 产物 | 路径 |
|---|---|
| 科技树预制体 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/TechTree/TechTree_{VehicleID}.prefab |
| 派系树预制体 | Assets/Art_Out/UI/Prefab/Interface_Vehicle/TechTree/{VehicleType}_0.prefab |
六、运行时加载
运行时由 UI_VehicleTechTreeController 从 Interface_Vehicle/TechTree/ 路径加载对应预制体,实例化到 UI 界面中显示。控制器负责:
- 按派系(VehicleType)切换不同的科技树
- 显示载具解锁状态
- 处理节点点击事件(跳转到部件树详情)
- 动态更新节点和箭头状态
七、关键类关系图
TreeEditorWindow (Odin编辑器窗口)
│
└── TreeEditPreload (预加载器/单例)
│
├── EditorTableManager (配置表加载)
│
└── VehicleTreeManager : TreeEditorManager (核心管理器)
│
├── TileManager (节点模板管理)
│ └── TilePrefabs[0..4] (5个模板预制体)
│
├── Node (节点数据)
│ ├── NodeId, parentsID, childrenIDs, depth
│ └── tile (对应的 GameObject)
│
├── UILineRenderer (连线绘制)
│
├── TreeHelpers (Reingold-Tilford 分层布局)
│
└── PloegTreeLayout (Ploeg 非分层布局)
VehicleCultivateManager (运行时 & 编辑器共用)
└── LoadVehicleTreeNode() ← 静态方法,解析配置表生成 VehicleTreeNode / VehicleComponentTreeNode