HOME / 第 7 部分 · 完整游戏项目实战 / 第 91 课
MODULE 7 · 完整游戏项目实战

第 91 课 · 2D RPG 实战(二):NPC 与对话

⏱ 预计时长 50 分钟📊 难度 进阶📚 模块 第 7 部分 · 完整游戏项目实战

🎯 本课学习目标

RPG 第二课:NPC 对话系统 + 简单任务。

📖 详细教学步骤

NPC 场景搭建

  1. 新建 npc.tscn,根 CharacterBody2D(或用 Area2D)
  2. Sprite2D/AnimatedSprite2D(NPC 形象)+ CollisionShape2D
  3. 挂脚本 npc.gd,带对话数据

对话数据结构代码

对话用数组(每句一行):

GDSCRIPTextends CharacterBody2D

@export var npc_name: String = "村民"
@export var dialogues: Array[String] = [
    "你好,冒险者!",
    "村外的森林最近出现了怪物...",
    "如果你能消灭它们,我会给你奖励!",
]
var dialogue_index: int = 0

交互触发代码

玩家靠近按 E 对话:

GDSCRIPTextends Node2D

@onready var npc = $NPC
@onready var dialogue_ui = $UI/DialogueBox

func _unhandled_input(event):
    if event.is_action_pressed("interact"):
        # 找面前最近的 NPC(简化:全场景找最近的)
        var nearest = find_nearest_npc()
        if nearest:
            start_dialogue(nearest)

func start_dialogue(npc):
    dialogue_ui.show()
    dialogue_ui.set_npc(npc)
    dialogue_ui.show_line(0)

对话 UI搭建

  1. UI:底部对话面板(Panel)+ 名字 Label + 文本 Label
  2. 按空格/点击 → 下一句
  3. 说完隐藏面板
GDSCRIPT# dialogue_ui.gd
var current_npc
var line: int = 0

func set_npc(npc):
    current_npc = npc
    line = 0
    $NameLabel.text = npc.npc_name
    show_line(0)

func show_line(i: int):
    $TextLabel.text = current_npc.dialogues[i]

func _unhandled_input(event):
    if event.is_action_just_pressed("ui_accept"):
        if current_npc and line < current_npc.dialogues.size() - 1:
            line += 1
            show_line(line)
        else:
            hide()
            current_npc = null

简单任务(收集)代码

任务:消灭 3 只怪物 → 找 NPC 领奖:

GDSCRIPT# Globals.gd
var quest_progress: int = 0
const QUEST_GOAL: int = 3

# 击杀怪物时
func on_enemy_killed():
    quest_progress += 1
    if quest_progress >= QUEST_GOAL:
        quest_done = true

# NPC 对话最后检测任务状态
func on_dialogue_end(npc):
    if Globals.quest_done and not npc.reward_given:
        npc.reward_given = true
        Globals.gold += 100
        show_message("获得 100 金币奖励!")

对话头像与打字(进阶)进阶

  • 对话可加头像:TextureRect 切换 NPC 头像
  • 文字用打字机效果(第 33 课)
  • 分支选项(选择对话):用 Button 列表
  • 任务系统可扩展成「任务列表 UI」
⚠️
按 E 没反应?

确认 interact 动作存在、NPC 在交互范围内、UI 隐藏状态正确。

⚠️
对话点太快跳词?

打字机效果时禁止跳行,播完才允许下一句。

🧪 动手试一试

🏋️ 课后练习

做一个 2 个 NPC 的村庄:村长给任务、商人卖东西(对话触发商店面板)。

NPC 脚本区分类型(quest/shop),对话后触发不同 UI。

💡

对话文本放资源(JSON)里,方便改剧情。

💡

按 E 交互 + 打字机对话是 RPG 标配,务必做顺。

🎓 本课小结

RPG 对话:NPC 带对话数组 + 按 E 触发 + 对话 UI 逐句显示 + 任务进度追踪;可扩展头像/分支/商店。