<< All versions

Skill v1.0.0

currentAutomated scan100/100
925236118/alphaagent/godot-interactive-system
──Details
PublishedOctober 14, 2026 at 08:17 PM
Content Hashsha256:9c5e75b2575394b6...
Git SHAed0da309bf4d
──Files
Files (1 file, 6.0 KB)
SKILL.md6.0 KBactive
SKILL.md · 239 lines · 6.0 KB

version: "1.0.0" name: godot-interactive-system description: Godot 4 可交互组件设计,包含InteractiveComponent代理组件、NPC对话、区域触发。


Godot 可交互组件设计

概述

可交互组件系统用于实现玩家与游戏世界中各种对象的交互,如 NPC 对话、场景切换、商店等。系统采用代理模式,通过 InteractiveComponent 统一管理交互检测和事件分发。

1. 架构设计

1.1 整体架构

玩家角色 (CharacterBase)
│
├── Talk Area2D (collision_mask = 256) ← 交互检测区域
│ │
│ └── Area Entered/Exited Signals
│
└── try_interact() ← 按 "talk" 键触发
│
├── talk_target.player_interact() [NPC对话]
│
└── interactable_area.interact() [关卡出口/商店]

1.2 可交互对象类型

类型实现方式触发方式
NPC 对话npc_base.gd按键触发
关卡出口interactable_level_exit.gd按键触发
商店自定义 player_interact按键触发
门自动检测区域进入自动触发

2. 交互检测机制

2.1 玩家端配置

gdscript
@onready var talk: Area2D = $Body/talk
var talk_target = null
var interactable_area = null

Talk Area 配置:

collision_layer = 0 # 不作为碰撞层
collision_mask = 256 # 检测位于256层的交互对象
monitorable = false # 不被其他 Area 检测

2.2 进入/离开交互区域

gdscript
func _on_talk_area_entered(area: Area2D) -> void:
if not area is InteractiveComponent:
return
if talk_target:
talk_target.exit_interact(self)
talk_target = null
if area.has_method("enter_interact"):
talk_target = area
talk_target.enter_interact(self)
func _on_talk_area_exited(area: Area2D) -> void:
if talk_target == area:
talk_target.exit_interact(self)
talk_target = null

2.3 交互触发

gdscript
func try_interact():
if (not talk.has_overlapping_areas() or not talk_target) and not interactable_area:
return
if talk_target and talk_target.has_method("player_interact"):
talk_target.player_interact(self)
return
if interactable_area:
interactable_area.interact(self)
return

3. InteractiveComponent 代理组件

3.1 核心实现

gdscript
class_name InteractiveComponent
extends Area2D
@export var agent: Node2D = null
func player_interact(player: CharacterBase):
if not agent:
return
agent.player_interact(player)
func enter_interact(player: CharacterBase):
if not agent:
return
agent.enter_interact(player)
func exit_interact(player: CharacterBase):
if not agent:
return
agent.exit_interact(player)

场景配置:

collision_layer = 256
collision_mask = 0
monitoring = false

3.2 代理模式优势

玩家交互请求
↓
InteractiveComponent.player_interact()
↓
agent.player_interact()
  • InteractiveComponent 可复用于不同对象
  • 业务逻辑放在 agent 中,便于维护
  • 可以动态切换 agent 改变交互行为

4. 常见交互类型

4.1 NPC 对话交互

gdscript
class_name NPCBase
extends CharacterBody2D
@export var interactable: bool = true
signal dialogue_started
func _physics_process(delta: float) -> void:
if interactable:
if can_talk_to_npc():
if Input.is_action_just_pressed("talk"):
if !interact_lock:
dialogue_in_progress = true
dialogue_started.emit()

4.2 关卡出口交互

普通出口 - 进入即触发:

gdscript
class_name LevelExit
extends Area2D
func _on_body_entered(body: Node2D):
if body is CharacterBase:
body.position = Vector2(-10000, -10000)
body.hide()
LevelManager.call_deferred("change_scene",
LevelManager.ChangeSceneParam.new(target_scene_path, target_scene_entry_tag))

可交互出口 - 需按键触发:

gdscript
class_name InteractableLevelExit
extends LevelExit
func interact(body):
body.position = Vector2(-10000, -10000)
body.hide()
LevelManager.call_deferred("change_scene",
LevelManager.ChangeSceneParam.new(target_scene_path, target_scene_entry_tag))

4.3 商店交互

gdscript
func player_interact(player: CharacterBase):
var game_operation = handle_game_operation.bind(player)
GameDirector.wait_game.connect(game_operation)
GameDirector.load_chapter("res://chapters/store_test.json")
await GameDirector.finished
GameDirector.wait_game.disconnect(game_operation)
func enter_interact(player: CharacterBase):
var interact_material := ShaderMaterial.new()
interact_material.shader = load("res://resource/shaders/border.gdshader")
interact_material.set_shader_parameter("outline_color", Color(1, 1, 1, 1))
sprite_2d.material = interact_material
func exit_interact(_player: CharacterBase):
sprite_2d.material = null

4.4 门交互(自动触发)

gdscript
enum DoorState { CLOSED, OPEN_LEFT, OPEN_RIGHT }
func _on_left_in_body_entered(body: Node2D) -> void:
if door_state == DoorState.CLOSED:
door_state = DoorState.OPEN_RIGHT
animated_sprite_2d.play("open_right")

5. 交互对象场景配置

可交互对象
│
├── InteractiveComponent (collision_layer = 256)
│ │
│ └── agent: Node2D ← 实际处理逻辑的节点
│
├── NPC (npc_base.gd)
│
├── InteractableLevelExit (interactable_level_exit.gd)
│
└── Store (自定义 player_interact)

6. 设计模式总结

模式应用场景
代理模式InteractiveComponent 转发交互请求给 agent
观察者模式talk_target 跟踪当前交互目标
状态机NPC 行为状态管理
导演模式GameDirector 统一管理游戏流程
All versions