Files
whale-town-front/docs/02-开发规范/架构与通信规范.md
moyin 0edd1c740b docs: 完善项目文档和README,修复字符显示问题
- 修复README.md中的emoji字符显示问题
- 移除文档质量评级系统
- 添加贡献者致谢部分,创建详细的CONTRIBUTORS.md
- 创建核心系统文件EventNames.gd和ProjectPaths.gd
- 更新项目配置文件project.godot,添加输入映射
- 完善各模块文档,修正路径引用问题
- 创建文档更新日志CHANGELOG.md
- 优化文档结构和导航系统
2025-12-31 18:58:38 +08:00

280 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 架构与通信规范
本文档定义了WhaleTown项目的架构设计原则和组件间通信规范。
## 🏛️ 架构设计原则
### 核心原则
- **"信号向上,调用向下"** - 父节点调用子节点方法,子节点发出信号通知父节点
- **高度解耦** - 通过事件系统实现组件间通信,避免直接依赖
- **分层架构** - 严格的三层架构:框架层、游戏层、界面层
- **单一职责** - 每个组件只负责一个明确的功能
### 分层架构详解
```
┌─────────────────────────────────────┐
│ UI Layer (界面层) │
│ UI/Windows/, UI/HUD/ │
├─────────────────────────────────────┤
│ Scenes Layer (游戏层) │
│ Scenes/Maps/, Scenes/Entities/ │
├─────────────────────────────────────┤
│ _Core Layer (框架层) │
│ _Core/managers/, _Core/systems/ │
└─────────────────────────────────────┘
```
## 🔄 事件系统 (EventSystem)
### 事件系统位置
- **文件路径**: `_Core/systems/EventSystem.gd`
- **自动加载**: 必须设置为AutoLoad单例
- **作用**: 全局事件总线,实现跨模块通信
### 事件命名规范
所有事件名称必须在 `_Core/EventNames.gd` 中定义:
```gdscript
# _Core/EventNames.gd
class_name EventNames
# 玩家相关事件
const PLAYER_MOVED = "player_moved"
const PLAYER_HEALTH_CHANGED = "player_health_changed"
const PLAYER_DIED = "player_died"
# 交互事件
const INTERACT_PRESSED = "interact_pressed"
const NPC_TALKED = "npc_talked"
const ITEM_COLLECTED = "item_collected"
# UI事件
const UI_BUTTON_CLICKED = "ui_button_clicked"
const DIALOG_OPENED = "dialog_opened"
const DIALOG_CLOSED = "dialog_closed"
# 游戏状态事件
const GAME_PAUSED = "game_paused"
const GAME_RESUMED = "game_resumed"
const SCENE_CHANGED = "scene_changed"
```
### 事件使用方法
#### 发送事件
```gdscript
# 发送简单事件
EventSystem.emit_event(EventNames.PLAYER_MOVED)
# 发送带数据的事件
EventSystem.emit_event(EventNames.PLAYER_HEALTH_CHANGED, {
"old_health": 80,
"new_health": 60,
"damage": 20
})
```
#### 监听事件
```gdscript
func _ready() -> void:
# 连接事件监听
EventSystem.connect_event(EventNames.PLAYER_DIED, _on_player_died)
EventSystem.connect_event(EventNames.ITEM_COLLECTED, _on_item_collected)
func _on_player_died(data: Dictionary = {}) -> void:
print("玩家死亡,游戏结束")
# 处理玩家死亡逻辑
func _on_item_collected(data: Dictionary) -> void:
var item_name = data.get("item_name", "未知物品")
print("收集到物品: ", item_name)
```
#### 断开事件监听
```gdscript
func _exit_tree() -> void:
# 节点销毁时断开事件监听
EventSystem.disconnect_event(EventNames.PLAYER_DIED, _on_player_died)
EventSystem.disconnect_event(EventNames.ITEM_COLLECTED, _on_item_collected)
```
## 🎯 单例管理器
### 允许的自动加载单例
项目中允许以下五个核心单例:
1. **GameManager** - 游戏状态管理
- 路径: `_Core/managers/GameManager.gd`
- 职责: 游戏状态、场景数据、全局配置
2. **SceneManager** - 场景管理
- 路径: `_Core/managers/SceneManager.gd`
- 职责: 场景切换、场景生命周期
3. **EventSystem** - 事件系统
- 路径: `_Core/systems/EventSystem.gd`
- 职责: 全局事件通信
4. **NetworkManager** - 网络管理
- 路径: `_Core/managers/NetworkManager.gd`
- 职责: HTTP请求、API调用、网络状态管理
5. **ResponseHandler** - 响应处理
- 路径: `_Core/managers/ResponseHandler.gd`
- 职责: 统一响应处理、错误处理、用户反馈
### 单例使用规范
```gdscript
# ✅ 正确:高层组件可以访问单例
func _ready() -> void:
var current_scene = SceneManager.get_current_scene()
var game_state = GameManager.get_game_state()
# ❌ 错误底层实体不应直接访问GameManager
# 在Player.gd或NPC.gd中避免这样做
func _ready() -> void:
GameManager.register_player(self) # 不推荐
# ✅ 正确:使用事件系统
func _ready() -> void:
EventSystem.emit_event(EventNames.PLAYER_SPAWNED, {"player": self})
```
## 🔗 组件通信模式
### 1. 父子通信
```gdscript
# 父节点调用子节点方法(向下调用)
func _on_button_pressed() -> void:
child_component.activate()
child_component.set_data(some_data)
# 子节点发出信号通知父节点(向上信号)
# 在子节点中:
signal component_activated(data: Dictionary)
signal component_finished()
func _some_action() -> void:
component_activated.emit({"status": "active"})
```
### 2. 兄弟组件通信
```gdscript
# 通过共同的父节点中转
# 或使用事件系统
func _notify_sibling() -> void:
EventSystem.emit_event(EventNames.COMPONENT_MESSAGE, {
"sender": self,
"message": "Hello sibling!"
})
```
### 3. 跨场景通信
```gdscript
# 使用事件系统进行跨场景通信
func _change_scene_with_data() -> void:
EventSystem.emit_event(EventNames.SCENE_DATA_TRANSFER, {
"target_scene": "battle_scene",
"player_data": player_data
})
```
## 🚫 禁止的通信模式
### 1. 直接节点引用
```gdscript
# ❌ 错误:直接获取其他场景的节点
func _bad_communication() -> void:
var other_scene = get_tree().get_first_node_in_group("other_scene")
other_scene.do_something() # 强耦合,难以维护
```
### 2. 全局变量传递
```gdscript
# ❌ 错误:使用全局变量传递状态
# 在autoload中
var global_player_data = {} # 避免这种做法
```
### 3. 循环依赖
```gdscript
# ❌ 错误A依赖BB又依赖A
# ComponentA.gd
var component_b: ComponentB
# ComponentB.gd
var component_a: ComponentA # 循环依赖
```
## 📋 通信最佳实践
### 1. 事件数据结构
```gdscript
# 使用结构化的事件数据
EventSystem.emit_event(EventNames.PLAYER_ATTACK, {
"attacker": self,
"target": target_enemy,
"damage": damage_amount,
"attack_type": "melee",
"timestamp": Time.get_time_dict_from_system()
})
```
### 2. 错误处理
```gdscript
func _on_event_received(data: Dictionary) -> void:
# 验证数据完整性
if not data.has("required_field"):
push_error("事件数据缺少必需字段: required_field")
return
# 安全地获取数据
var value = data.get("optional_field", default_value)
```
### 3. 性能考虑
```gdscript
# 避免在_process中频繁发送事件
var last_position: Vector2
func _process(delta: float) -> void:
if global_position.distance_to(last_position) > 10.0:
EventSystem.emit_event(EventNames.PLAYER_MOVED, {
"position": global_position
})
last_position = global_position
```
## 🧪 测试通信系统
### 单元测试示例
```gdscript
extends GutTest
func test_event_emission():
# 监听事件
watch_signals(EventSystem)
# 发送事件
EventSystem.emit_event(EventNames.PLAYER_MOVED, {"x": 100, "y": 200})
# 验证事件发送
assert_signal_emitted(EventSystem, "event_raised")
func test_event_data():
var received_data: Dictionary
# 连接事件监听
EventSystem.connect_event(EventNames.TEST_EVENT, func(data): received_data = data)
# 发送测试数据
var test_data = {"test": "value"}
EventSystem.emit_event(EventNames.TEST_EVENT, test_data)
# 验证数据传递
assert_eq(received_data, test_data)
```
---
**记住:良好的架构设计是项目成功的基石!遵循这些通信规范可以确保代码的可维护性和扩展性。**