📌 为什么继承 Resource
?
-
Resource
是一个轻量的对象类型,通常用于保存数据(比如对话、配置、技能数据等),而不是控制场景中的节点逻辑。 -
如果你想创建一个可以被序列化、保存并重复使用的数据结构,比如:
- 一个对话系统中的每段对话
- 游戏角色的配置文件
- 技能、任务、物品等定义
那么继承Resource
是一种很合适的做法。
``
extends
class_name Dialogue # 定义一个可在全局使用的资源类,文件名可以直接对应 class_name
@export var character_name : String
# 导出一个字符串变量,用于存储角色名字,在 Inspector 中可视化编辑
@export_multiline var content : String
# 导出一个多行文本变量,适合较长的对话内容,Inspector 中会显示一个大文本框
@export var avatar : Texture
# 导出一个 Texture 类型变量,可以在 Inspector 中拖入角色头像图片资源
@export var show_on_left : bool
# 导出一个布尔型变量,用于在对话框显示时判断该角色头像是在左侧还是右侧
行号 | 原代码 | 说明 |
---|---|---|
1 | extends Resource |
继承 Godot 的 Resource 类,使其可以作为资源保存和共享 |
2 | class_name Dialogue |
定义全局类名,方便在其他脚本 @export var dialogue: Dialogue 中使用 |
4 | @export var character_name : String |
导出接口供 Inspector 直接编辑角色名 |
6 | @export_multiline var content : String |
多行文本编辑器,适合输入对话内容 |
8 | @export var avatar : Texture |
导入头像贴图,资源编辑器可拖拽赋值 |
10 | @export var show_on_left : bool |
控制头像显示方向,左或右,布尔值直观控制界面布局 |
📋 为什么使用这些语法?
@export
,@export_multiline
是 Godot 4.x 新的属性导出语法,可让变量出现在编辑器 Inspector,方便赋值及配置extends Resource
+class_name
用于定义一个可序列化且全项目可引用的资源类,适合对话、技能、剧情等数据的统一管理与复用。@export_multiline
尤其适合长文本,自动命令 Inspector 显示大文本区域,提升易读性和编辑体验。
🎯 使用场景总结
- 在 Inspector 中可视化编辑:无需写代码赋值,通过界面配置对话内容、头像、位置等。
- 作为独立资源可复用 :可以创建多个
.tres
或.res
对话资源,多个 NPC 或对话事件使用同一个数据。 - 序列化与版本控制:对话内容存为资源文件,可纳入版本控制,便于管理与协作。
- 数据与逻辑解耦:该脚本只负责对话数据本身,逻辑交互部分可以另写脚本处理专属 UI 展示。

extends
class_name DialogueGroup # 将此脚本声明为一个全局资源类型,可以在 Inspector 创建或其他脚本引用
@export var dialogue_list : Array[Dialogue] = []
# 导出一个 Dialogue 类型的数组,Inspector 中可编辑
# 使用默认空数组 [],避免 dialogue_list 为 null,提高编辑体验

Control
└── HBoxContainer
├── LeftAvatar (TextureRect)
├── Panel
│ └── MarginContainer
│ └── VBoxContainer
│ ├── Name (Label)
│ └── Content (Label, Text 等)
└── RightAvatar (TextureRect)
📐 节点作用详解
HBoxContainer
- 水平排列子节点(左右),自动分配空间
- LeftAvatar 和 RightAvatar 分别居左和居右,Panel(对话内容)保持居中和伸缩。
LeftAvatar / RightAvatar (TextureRect)
- 用于显示角色头像。根据对话方向(左侧或右侧)选择显示哪一个,另一个可以隐藏或设置可见性。
Panel
- 通常是 PanelContainer,加上 MarginContainer 提供背景边框和阴影效果,同时截断输入
MarginContainer
- 为 Panel 内部内容提供内边距(padding),避免文本或头像贴边
VBoxContainer
- 垂直排列 Name 和 Content 标签,使角色名在上,内容在下
Label
-
显示单行或自动换行的纯文本,不支持文字高亮、图片等复杂格式
-
如果需要显示带有粗体、斜体、颜色、表情或图片的文本,应使用
RichTextLabel



🎯 属性解析
-
Texture:设置所显示的贴图(头像)。你可以直接从资源浏览器拖拽,也可点击小图标选择。
-
Expand Mode(扩展模式) :
控制节点最小尺寸的来源:
Keep Size
: 最小尺寸与贴图大小一致,不允许比贴图小。Ignore Size
: 忽略纹理尺寸,允许节点自由缩放(适合响应式布局)。- 还有其他按宽高适配的选项,如仅按宽度适配等stackoverflow.com+11docs.godotengine.org+11docs.w3cub.com+11。
-
Stretch Mode(拉伸模式) :
决定纹理在控制节点区域如何绘制:
Keep Aspect
: 等比缩放至充满节点边界,保持比例。Keep Size
: 保持原始尺寸,放在左上角。Keep Aspect Centered
: 等比缩放并居中显示。Scale
: 拉伸以完全填充节点矩形。
🧰 自动拉伸至填满父容器的全部空间,边距归零,尺寸与位置全由容器控制



✅ 总结
你看到的 Autowrap
四个选项分别控制不同的换行策略:
模式 | 描述 |
---|---|
Off | 不换行,整行显示 |
Arbitrary | 任意位置断行 |
Word | 单词边界换行 |
Word (Smart) | 智能单词和标点符号换行,过长单词拆分 |

目的 | 为什么继承 Control |
---|---|
UI 布局 | 支持锚点、Container、自动调整大小 |
事件交互 | 能响应鼠标点击、焦点、输入 |
容易编辑与维护 | 编辑器可视化布局、属性设置统一靠 Control |
场景结构清晰 | UI 代码集中在 UI 根节点,逻辑清晰、扩展方便 |
extends
# 继承 Control,用于管理对话 UI 布局、输入事件等
@export_group("UI")
@export var character_name_text : Label
@export var text_box : Label
@export var left_avatar : TextureRect
@export var right_avatar : TextureRect
# 导出 UI 控件引用,在 Inspector 中绑定对应节点,便于脚本访问和修改
@export_group("对话")
@export var main_dialogue : DialogueGroup
# 导出对话组资源,Inspector 可选择 `.tres` 文件,方便对话数据关联
var dialogue_index := 0
# 用于记录当前对话的索引位置
var typing_tween : Tween
# 存储当前用于"打字效果"的 Tween
func display_next_dialogue():
# 展示下一条对话
if dialogue_index >= len(main_dialogue.dialogue_list):
visible = false
return
# 如果索引超出,隐藏整个对话 UI 并退出
var dialogue := main_dialogue.dialogue_list[dialogue_index]
# 获取当前 Dialogue 实例
if typing_tween and typing_tween.is_running():
# 如果打字动画还在运行,直接结束动画并显示完整文本
typing_tween.kill()
text_box.text = dialogue.content
dialogue_index += 1
else:
# 正常开启打字动画
character_name_text.text = dialogue.character_name
typing_tween = get_tree().create_tween()
text_box.text = ""
# 字母逐个显示
for character in dialogue.content:
typing_tween.tween_callback(append_character.bind(character)).set_delay(0.05)
# 每隔 0.05 秒执行一次 append_character,传入当前字符
# 使用 Callable.bind 参数传递方式,是 Godot 4 的推荐用法:contentReference[oaicite:1]{index=1}
typing_tween.tween_callback(func(): dialogue_index += 1)
# 在动画全部执行后,索引增加 1,准备下一句
# 根据对话方向控制头像显示
if dialogue.show_on_left:
left_avatar.texture = dialogue.avatar
right_avatar.texture = null
else:
left_avatar.texture = null
right_avatar.texture = dialogue.avatar
func append_character(character : String):
text_box.text += character
# 将传入的字符追加到对话内容 Label 中
func _ready():
display_next_dialogue()
# 场景加载完成后立即开启第一句对话
func _on_click(event):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
display_next_dialogue()
# 捕获点击事件,如果是左键按下,就播放下一句或跳过动画
Godot 中的 Tween:
它是一个轻量级对象,用脚本创建,能在运行时对属性进行平滑动画控制,例如位置、颜色、透明度、文本逐字显示等