This commit is contained in:
meishibiezb
2026-06-04 21:37:53 +08:00
parent b0d2a0e2e7
commit 29a3f77908
63 changed files with 4068 additions and 1 deletions

View File

@@ -0,0 +1,85 @@
# UDialogPresentationSubsystem
## 基本信息
- **类型**: UCLASS
- **父类**: UGameInstanceSubsystem
- **源文件**: Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h
- **模块**: Dialog
## 功能概述
GameInstance 级别的对话数据中心注册表。管理脚本数据FDialogPresentationScriptData和映射表FDialogTextData的 DataTable 注册。构建 O(1) 文本查找索引。ShowDialog 将所有环节串联起来:通过 StructID 查找脚本、注入 ScriptID、调用执行器的 ExecutePresentationScript。
## 设计用意
对话系统的数据访问层。使用 UGameInstanceSubsystem 以获得持久生命周期。支持多个 DataTable按章节、按 NPC 等)。通过预构建的哈希映射实现 O(1) 文本查找,满足频繁的游戏查询需求。将数据与执行解耦。
## 职责范围
对话数据中心注册表与查找。注册/注销 DataTable。构建文本索引。通过 StructID 解析脚本。不执行脚本(委托给执行器),也不解析 JSON使用 UPresentationJsonLibrary
## 项目内依赖
| 依赖项 | 关系 | 源文件 |
|--------|------|--------|
| FDialogTextData | 前向声明 | Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h:11 |
| IPresentationScriptExecutor | 前向声明(参数) | Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h:32 |
| FDialogPresentationScriptData | #include(在 .cpp 中) | Plugins/Dialog/Source/Dialog/Public/DialogPresentationScript.h |
## 对外接口
UGameInstanceSubsystem 派生类,所有方法均为 UFUNCTION(BlueprintCallable),可从 C++ 和蓝图调用。UE 引擎自动创建实例(每个 GameInstance 一个),无需手动实例化。
脚本执行:
- **ShowDialog(const TScriptInterface<IPresentationScriptExecutor> Executor, const FName StructID)**: 核心入口。在所有已注册的 DataTable 中按 StructID 查找 FDialogPresentationScriptData注入 ScriptID然后调用 Executor 的 ExecutePresentationScript 接口方法。
数据查询:
- **GetDialogPresentationScriptData(const FName StructID)**: 遍历 RegisteredDataTables返回第一个匹配 StructID 的行。返回时会注入 ScriptID 字段。
- **GetDialogTextFromMapTable(FName Source)**: 从 DialogTextIndex 中按 Source 查找对话文本O(1) 复杂度。首次调用时若索引未构建则自动触发 BuildIndexes()。
- **GetChoiceTextFromMapTable(FName Source, FName Target)**: 从 ChoiceTextIndex 中按复合键 `Source|Target` 查找选项文本数组O(1) 复杂度。首次调用时若索引未构建则自动触发 BuildIndexes()。
DataTable 管理:
- **RegisterDataTable(const FName TableName, UDataTable* DataTable)**: 注册脚本 DataTable。TableName 仅供标识,查找时遍历所有已注册表。
- **UnregisterDataTable(const FName TableName)**: 注销脚本 DataTable。
- **RegisterMapTable(const FName TableName, UDataTable* DataTable)**: 注册文本映射 DataTableFDialogTextData。注册时自动调用 BuildIndexes() 重建索引。
- **UnregisterMapTable(const FName TableName)**: 注销文本映射 DataTable 并重建索引。
内部状态(对外不可见):
- RegisteredDataTables (TMap<FName, UDataTable*>): 已注册的脚本 DataTable。
- RegisteredMapTables (TMap<FName, UDataTable*>): 已注册的文本映射 DataTable。
- DialogTextIndex (TMap<FName, FDialogTextData>): 按 Source 索引的对话文本映射。
- ChoiceTextIndex (TMap<FName, FHelperArray>): 按 `Source|Target` 复合键索引的选项文本映射。
## 使用方法
通过 GameInstance 获取子系统实例:
```cpp
UGameInstance* GI = GetGameInstance();
UDialogPresentationSubsystem* DialogSubsystem = GI->GetSubsystem<UDialogPresentationSubsystem>();
```
调用 ShowDialog 触发脚本执行:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:8-17
DialogSubsystem->ShowDialog(ExecutorWidget, FName("StartNode"));
```
注册 DataTable 和 MapTable
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:43,56
DialogSubsystem->RegisterDataTable(FName("Chapter1"), ScriptTable);
DialogSubsystem->RegisterMapTable(FName("Chapter1"), MapTable);
```
查询对话文本:
```cpp
// Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp:71-81
FDialogTextData Text = DialogSubsystem->GetDialogTextFromMapTable(FName("Node_01"));
```
## 用例
| 文件 | 行号 | 用途 |
|------|------|------|
| Plugins/Dialog/Source/Dialog/Public/DialogPresentationSubsystem.h | 26-70 | 类定义:所有公共方法声明和私有成员 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 8-17 | ShowDialog 实现:校验接口 + 调用 Execute_ExecutePresentationScript |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 20-41 | GetDialogPresentationScriptData 实现:遍历已注册表查找行 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 43-53 | RegisterDataTable / UnregisterDataTable 实现 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 56-68 | RegisterMapTable / UnregisterMapTable 实现(含自动索引重建) |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 71-81 | GetDialogTextFromMapTable 实现O(1) 查找 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 84-96 | GetChoiceTextFromMapTable 实现:按复合键 O(1) 查找 |
| Plugins/Dialog/Source/Dialog/Private/DialogPresentationSubsystem.cpp | 98-127 | BuildIndexes 实现:遍历 MapTable 构建 DialogTextIndex 和 ChoiceTextIndex |
| Document/Content/Blueprints/WBP_TestUI.md | 16,24 | WBP_TestUI 通过 UDialogPresentationSubsystem 管理 DataTable |