From ed30e9238f4f2193095b8cbc700f3b486a377200 Mon Sep 17 00:00:00 2001 From: liutao <821580467@qq.com> Date: Fri, 6 Feb 2026 16:56:51 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90AI=E7=BC=96=E7=A0=81=E3=80=91=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AI_Gen_Doc/载具科技树生成功能说明.md | 222 ++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 ProjectNLD/AI_Gen_Doc/载具科技树生成功能说明.md diff --git a/ProjectNLD/AI_Gen_Doc/载具科技树生成功能说明.md b/ProjectNLD/AI_Gen_Doc/载具科技树生成功能说明.md new file mode 100644 index 00000000000..9ba358d8454 --- /dev/null +++ b/ProjectNLD/AI_Gen_Doc/载具科技树生成功能说明.md @@ -0,0 +1,222 @@ +# 载具科技树生成 功能说明 + +## 一、功能概述 + +载具科技树生成是一个 **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 按钮触发: + +```csharp +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 +```