Files
whale-town-front/docs/04-高级开发/模块开发指南.md
moyin 1ff677b3b2 docs: 重新组织文档结构,按开发阶段分类
新的目录结构:
  01-项目入门/     # 新人必读,项目基础
  02-开发规范/     # 编码标准和规范
  03-技术实现/     # 具体开发指导
  04-高级开发/     # 进阶开发技巧
  05-部署运维/     # 发布和部署
  06-功能模块/     # 特定功能文档

 新增导航文档:
- docs/README.md - 完整的文档导航和使用指南
- 各目录下的README.md - 分类说明和使用指导

 优化效果:
- 开发者可以按阶段快速定位需要的文档
- 新人有清晰的学习路径
- 不同角色有针对性的文档推荐
- 提供了问题导向的快速查找功能
2025-12-31 18:02:16 +08:00

464 lines
11 KiB
Markdown
Raw 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.
# 模块开发指南
本文档详细说明如何在 Whale Town 项目中开发新的游戏模块。
## 🎯 模块设计原则
### 核心原则
1. **单一职责** - 每个模块只负责一个特定的游戏功能
2. **高内聚低耦合** - 模块内部紧密相关,模块间松散耦合
3. **可复用性** - 模块应该能在不同场景中复用
4. **标准化接口** - 统一的模块接口和通信方式
5. **测试友好** - 模块应该易于测试和调试
### 模块分类
- **UI模块** - 用户界面组件和交互逻辑
- **游戏逻辑模块** - 角色、战斗、对话等核心功能
- **系统模块** - 存档、设置、网络等系统功能
- **工具模块** - 通用工具和辅助功能
## 🏗️ 模块结构
### 标准目录结构
```
module/YourModule/
├── YourModule.gd # 主模块脚本
├── components/ # 子组件
│ ├── Component1.gd
│ └── Component2.gd
├── data/ # 模块数据
│ ├── module_config.json
│ └── default_data.json
├── scenes/ # 模块场景
│ ├── YourModule.tscn
│ └── components/
├── tests/ # 模块测试
│ ├── test_your_module.gd
│ └── test_components.gd
└── README.md # 模块文档
```
### 文件命名规范
- **主模块脚本**: `ModuleName.gd` (PascalCase)
- **组件脚本**: `ComponentName.gd` (PascalCase)
- **场景文件**: `module_name.tscn` (snake_case)
- **数据文件**: `snake_case.json`
- **测试文件**: `test_module_name.gd`
## 📝 模块开发步骤
### 第一步:创建模块结构
```bash
# 创建模块目录
mkdir module/YourModule
cd module/YourModule
# 创建子目录
mkdir components data scenes tests
# 创建主要文件
touch YourModule.gd
touch README.md
touch data/module_config.json
```
### 第二步:实现模块接口
每个模块都应该实现标准的模块接口:
```gdscript
# YourModule.gd
extends Node
class_name YourModule
# 模块信息
const MODULE_NAME = "YourModule"
const MODULE_VERSION = "1.0.0"
const MODULE_AUTHOR = "Your Name"
# 模块状态
enum ModuleState {
UNINITIALIZED,
INITIALIZING,
READY,
ERROR
}
var current_state: ModuleState = ModuleState.UNINITIALIZED
var config: Dictionary = {}
var is_enabled: bool = true
# 必需接口方法
func initialize() -> bool:
"""初始化模块"""
current_state = ModuleState.INITIALIZING
# 加载配置
if not _load_config():
current_state = ModuleState.ERROR
return false
# 初始化组件
if not _initialize_components():
current_state = ModuleState.ERROR
return false
# 注册事件监听
_register_events()
current_state = ModuleState.READY
return true
func cleanup():
"""清理模块资源"""
_unregister_events()
_cleanup_components()
current_state = ModuleState.UNINITIALIZED
func get_module_info() -> Dictionary:
"""获取模块信息"""
return {
"name": MODULE_NAME,
"version": MODULE_VERSION,
"author": MODULE_AUTHOR,
"state": current_state,
"enabled": is_enabled
}
# 私有方法
func _load_config() -> bool:
"""加载模块配置"""
var config_path = "res://module/%s/data/module_config.json" % MODULE_NAME
if not FileAccess.file_exists(config_path):
print("警告: 模块配置文件不存在: ", config_path)
return true # 使用默认配置
var file = FileAccess.open(config_path, FileAccess.READ)
if file == null:
print("错误: 无法读取配置文件: ", config_path)
return false
var json_string = file.get_as_text()
file.close()
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result != OK:
print("错误: 配置文件JSON格式错误: ", config_path)
return false
config = json.data
return true
func _initialize_components() -> bool:
"""初始化子组件"""
# 在这里初始化模块的子组件
return true
func _cleanup_components():
"""清理子组件"""
# 在这里清理模块的子组件
pass
func _register_events():
"""注册事件监听"""
# 使用EventSystem注册需要监听的事件
# EventSystem.connect_event("event_name", _on_event_handler)
pass
func _unregister_events():
"""取消事件监听"""
# 取消所有事件监听
# EventSystem.disconnect_event("event_name", _on_event_handler)
pass
```
### 第三步:创建模块配置
```json
// data/module_config.json
{
"module_name": "YourModule",
"version": "1.0.0",
"enabled": true,
"dependencies": [],
"settings": {
"auto_initialize": true,
"debug_mode": false
},
"resources": {
"textures": [],
"sounds": [],
"data_files": []
}
}
```
### 第四步:实现具体功能
根据模块类型实现具体功能:
#### UI模块示例
```gdscript
# UI模块应该继承Control或其子类
extends Control
class_name UIModule
signal ui_event_triggered(event_name: String, data: Dictionary)
func show_ui():
"""显示UI"""
visible = true
# 播放显示动画
_play_show_animation()
func hide_ui():
"""隐藏UI"""
# 播放隐藏动画
_play_hide_animation()
await get_tree().create_timer(0.3).timeout
visible = false
func _play_show_animation():
"""播放显示动画"""
var tween = create_tween()
modulate.a = 0.0
tween.tween_property(self, "modulate:a", 1.0, 0.3)
func _play_hide_animation():
"""播放隐藏动画"""
var tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, 0.3)
```
#### 游戏逻辑模块示例
```gdscript
# 游戏逻辑模块
extends Node
class_name GameLogicModule
signal state_changed(old_state: String, new_state: String)
signal data_updated(data_type: String, new_data: Dictionary)
var module_data: Dictionary = {}
var current_state: String = "idle"
func process_game_logic(delta: float):
"""处理游戏逻辑"""
match current_state:
"idle":
_process_idle_state(delta)
"active":
_process_active_state(delta)
"paused":
_process_paused_state(delta)
func change_state(new_state: String):
"""改变模块状态"""
var old_state = current_state
current_state = new_state
state_changed.emit(old_state, new_state)
func update_data(data_type: String, new_data: Dictionary):
"""更新模块数据"""
module_data[data_type] = new_data
data_updated.emit(data_type, new_data)
```
### 第五步:添加测试
```gdscript
# tests/test_your_module.gd
extends "res://addons/gut/test.gd"
var module: YourModule
func before_each():
module = YourModule.new()
add_child(module)
func after_each():
module.queue_free()
func test_module_initialization():
assert_true(module.initialize(), "")
assert_eq(module.current_state, YourModule.ModuleState.READY, "READY")
func test_module_cleanup():
module.initialize()
module.cleanup()
assert_eq(module.current_state, YourModule.ModuleState.UNINITIALIZED, "UNINITIALIZED")
func test_module_info():
var info = module.get_module_info()
assert_true(info.has("name"), "")
assert_true(info.has("version"), "")
assert_eq(info.name, "YourModule", "")
```
### 第六步:编写文档
```markdown
# YourModule 模块
## 功能描述
简要描述模块的主要功能和用途。
## 使用方法
```gdscript
# 创建和初始化模块
var your_module = YourModule.new()
add_child(your_module)
your_module.initialize()
# 使用模块功能
your_module.some_function()
```
## API参考
### 公共方法
- `initialize() -> bool` - 初始化模块
- `cleanup()` - 清理模块资源
- `get_module_info() -> Dictionary` - 获取模块信息
### 信号
- `signal_name(param: Type)` - 信号描述
## 配置选项
描述模块的配置选项和默认值。
## 依赖关系
列出模块的依赖项。
## 注意事项
使用模块时需要注意的事项。
```
## 🔧 模块集成
### 在场景中使用模块
```gdscript
# 在场景脚本中使用模块
extends Control
var inventory_module: InventoryModule
var dialogue_module: DialogueModule
func _ready():
# 创建并初始化模块
inventory_module = InventoryModule.new()
add_child(inventory_module)
inventory_module.initialize()
dialogue_module = DialogueModule.new()
add_child(dialogue_module)
dialogue_module.initialize()
# 连接模块事件
inventory_module.item_selected.connect(_on_item_selected)
dialogue_module.dialogue_finished.connect(_on_dialogue_finished)
func _on_item_selected(item_data: Dictionary):
print("选中物品: ", item_data.name)
func _on_dialogue_finished():
print("对话结束")
```
### 模块间通信
推荐使用EventSystem进行模块间通信
```gdscript
# 发送事件
EventSystem.emit_event("inventory_item_used", {
"item_id": "potion_001",
"quantity": 1
})
# 监听事件
EventSystem.connect_event("inventory_item_used", _on_item_used)
func _on_item_used(data: Dictionary):
print("使用了物品: ", data.item_id)
```
## 🧪 测试和调试
### 单元测试
每个模块都应该有对应的单元测试:
```bash
# 运行模块测试
godot --headless --script tests/test_your_module.gd
```
### 调试技巧
1. **使用print语句** - 在关键位置添加调试输出
2. **断点调试** - 在Godot编辑器中设置断点
3. **状态监控** - 实时监控模块状态变化
4. **事件追踪** - 记录事件的发送和接收
### 性能监控
```gdscript
# 性能监控示例
func _process(delta):
var start_time = Time.get_time_dict_from_system()
# 执行模块逻辑
process_module_logic(delta)
var end_time = Time.get_time_dict_from_system()
var execution_time = (end_time.hour * 3600 + end_time.minute * 60 + end_time.second) - \
(start_time.hour * 3600 + start_time.minute * 60 + start_time.second)
if execution_time > 0.016: # 超过16ms
print("警告: 模块执行时间过长: ", execution_time, "")
```
## 📚 最佳实践
### 代码质量
1. **遵循命名规范** - 使用清晰、一致的命名
2. **添加详细注释** - 解释复杂逻辑和设计决策
3. **错误处理** - 妥善处理各种异常情况
4. **资源管理** - 及时释放不需要的资源
### 性能优化
1. **避免频繁的内存分配** - 重用对象和数据结构
2. **合理使用信号** - 避免过多的信号连接
3. **批量处理** - 将多个操作合并处理
4. **延迟加载** - 按需加载资源和数据
### 可维护性
1. **模块化设计** - 保持模块的独立性
2. **版本控制** - 记录模块的版本变化
3. **文档更新** - 及时更新模块文档
4. **向后兼容** - 考虑API的向后兼容性
## 🔍 常见问题
### Q: 如何处理模块依赖?
A: 在模块配置中声明依赖,在初始化时检查依赖是否满足。
### Q: 模块间如何共享数据?
A: 使用EventSystem传递数据或通过GameManager等全局管理器。
### Q: 如何调试模块问题?
A: 使用Godot的调试工具添加日志输出编写单元测试。
### Q: 模块性能如何优化?
A: 避免在_process中执行重复计算使用对象池合理管理资源。
## 📖 参考资料
- [Godot官方文档](https://docs.godotengine.org/)
- [项目命名规范](./naming_convention.md)
- [代码注释规范](./code_comment_guide.md)
- [Git提交规范](./git_commit_guide.md)
---
**记住:好的模块设计是项目成功的关键!**