Back to Blog
·Summer Team

如何在 Godot 4 中制作 AI:分步指南(2026)

一份实用指南,带你从敌人状态机、寻路系统一步步走到 LLM 驱动的 NPC,附可直接粘贴使用的 GDScript,以及借助 AI 辅助引擎大幅提速的方法。

问「如何在 Godot 里做 AI」,你会得到两种完全不同的答案,因为同一个问题背后其实是两件毫不相关的事。

一种是经典游戏 AI:地精发现你、绕着柱子追你、靠近后挥刀攻击。这是决策逻辑加上移动控制,几十年来一直是游戏开发的基本功。

另一种是语言模型 AI:你可以用自己的话跟店主聊天,它会以角色身份回答。这是新兴技术,需要通过网络将文字发送给模型,解决的是另一个问题。

大多数游戏几乎所有地方都需要第一种 AI,只有少数几个需要对话的角色才会用到第二种。本指南按顺序讲解两种方案,附有可直接粘贴到 Godot 4 中使用的 GDScript。最后会介绍 AI 原生引擎如何替你编写这些代码并通过运行游戏来验证——这正是教程通常会跳过的部分。

第一部分:经典游戏 AI(你最常需要的那种)

当设计师说一个敌人「AI 很好」时,他们几乎从不是指它在运行神经网络。他们的意思是它做出了合理的决策:注意到玩家、选择合适的行动、随情况变化而改变策略。落实到代码里,就是状态机。

状态机是一组状态(待机、巡逻、追击、攻击)加上状态之间切换的规则。这是游戏 AI 中最实用的单一模式,而 Godot 4 提供了构建它所需的一切。

第一步:搭建敌人场景

新建一个场景,以 CharacterBody2D 作为根节点(3D 场景使用 CharacterBody3D,逻辑完全相同)。添加以下子节点:

  • Sprite2DAnimatedSprite2D,用于显示敌人
  • CollisionShape2D,给敌人添加碰撞体
  • 一个 Area2D,带有自己的 CollisionShape2D,尺寸大于敌人本身,用作检测范围
  • NavigationAgent2D,让敌人能够绕过障碍物移动

检测用的 Area2D 就是敌人的「感知器」。当玩家进入它的范围时,敌人就会做出反应。

第二步:编写状态机

将以下脚本挂载到根节点。它定义了四个状态,并根据与玩家的距离在状态之间切换。

extends CharacterBody2D

enum State { IDLE, PATROL, CHASE, ATTACK }

@export var move_speed: float = 120.0
@export var attack_range: float = 40.0

var state: State = State.IDLE
var player: Node2D = null

@onready var nav: NavigationAgent2D = $NavigationAgent2D

func _physics_process(_delta: float) -> void:
	match state:
		State.IDLE:
			velocity = Vector2.ZERO
			if player != null:
				state = State.CHASE
		State.CHASE:
			_chase()
		State.ATTACK:
			velocity = Vector2.ZERO
			_attack()
	move_and_slide()

func _chase() -> void:
	if player == null:
		state = State.IDLE
		return
	var distance := global_position.distance_to(player.global_position)
	if distance <= attack_range:
		state = State.ATTACK
		return
	nav.target_position = player.global_position
	var next_point := nav.get_next_path_position()
	velocity = global_position.direction_to(next_point) * move_speed

func _attack() -> void:
	# play attack animation, deal damage, then return to chase
	if player != null and global_position.distance_to(player.global_position) > attack_range:
		state = State.CHASE

# connect these from the detection Area2D in the editor
func _on_detection_area_body_entered(body: Node2D) -> void:
	if body.is_in_group("player"):
		player = body

func _on_detection_area_body_exited(body: Node2D) -> void:
	if body.is_in_group("player"):
		player = null
		state = State.IDLE

这段代码能正常运行,关键在于两点。match 语句按 state 分离了各个行为,后续添加新状态时不会相互干扰。Area2D 的 body_entered 和 body_exited 信号(从编辑器的 Node 面板连接)让敌人在「感知到」和「失去感知」之间切换,无需每帧轮询。

把你的玩家添加到 player 分组(选中它,打开 Node 面板,进入 Groups,添加 "player"),这样检测逻辑才能找到它。

第三步:添加寻路,让敌人能绕过墙壁

上面的脚本用到了 NavigationAgent2D,但导航代理需要一张地图来知道哪里是地面。在关卡场景中添加一个 NavigationRegion2D,并赋予它一个覆盖可行走地面的 NavigationPolygon,同时在墙壁位置挖出空洞。Godot 会自动为导航代理规划路径。

核心思路是:你的 AI 脚本决定目的地(nav.target_position = player.global_position),导航系统决定路径。你完全不需要自己写寻路算法。get_next_path_position() 返回下一个路径点,你只需朝它移动即可。

3D 场景的流程完全相同,使用 NavigationRegion3DNavigationAgent3D。你需要在关卡几何体上烘焙导航网格而不是手绘多边形,但脚本模式不变。

第四步:添加视线检测(可选,但很值得)

仅靠检测范围,敌人会穿墙「看见」你。要解决这个问题,添加一个 RayCast2D,在切换到追击状态之前先检查射向玩家的射线是否被遮挡。

func can_see_player() -> bool:
	if player == null:
		return false
	$RayCast2D.target_position = to_local(player.global_position)
	$RayCast2D.force_raycast_update()
	if $RayCast2D.is_colliding():
		return $RayCast2D.get_collider() == player
	return true

IDLE -> CHASE 的切换条件改为依赖 can_see_player(),敌人就需要真正的视线才能发现你,这会让玩家感觉游戏更公平、更聪明。

到这里,你就有了一个完整的、可直接发布的敌人 AI:检测、绕障碍追击、视线受墙壁阻挡、进入攻击范围后出手。巡逻路线、血量低时逃跑、群体战术——这些都只是在同一套骨架上增加更多状态和切换条件而已。

第二部分:LLM 驱动的 AI(会说话的 NPC)

「Godot 里的 AI」的第二种含义,是一个可以自由交谈的 NPC。这是一套完全不同的机制。它不是状态机,而是把文字发送给语言模型,再把回复转化为对话。

Godot 4 没有内置模型,但它有 HTTPRequest,这就是调用外部模型所需的全部工具。

第一步:向模型发送消息

添加一个 HTTPRequest 节点和一个脚本,将玩家的消息加上简短的角色描述一起发送给模型 API。

extends Node

@onready var http: HTTPRequest = $HTTPRequest

const ENDPOINT := "https://api.example-model.com/v1/chat"
const API_KEY := "your-key-here" # keep this out of shipped builds

func ask_npc(player_message: String) -> void:
	var headers := [
		"Content-Type: application/json",
		"Authorization: Bearer " + API_KEY,
	]
	var body := {
		"system": "You are Bram, a tired village blacksmith. Stay in character. Keep replies under two sentences.",
		"message": player_message,
	}
	http.request(ENDPOINT, headers, HTTPClient.METHOD_POST, JSON.stringify(body))

func _ready() -> void:
	http.request_completed.connect(_on_response)

func _on_response(_result, _code, _headers, response_body: PackedByteArray) -> void:
	var data = JSON.parse_string(response_body.get_string_from_utf8())
	var reply: String = data.get("reply", "...")
	show_dialogue(reply)

func show_dialogue(text: String) -> void:
	# push text into your dialogue UI
	print(text)

第二步:给 NPC 添加记忆

没有记忆的模型每次对话都会从零开始。要让铁匠记住你,需要维护一份历史对话列表,并在每次请求中附上简短的摘要。把它存储在 NPC 上,每轮对话追加一条记录;当历史记录太长时,让模型将旧对话总结成一两句话,避免提示词无限增长。

第三步:在投入之前了解权衡

LLM 对话功能强大,但也有代价。每条消息都要花钱,网络回传需要时间,还必须联网——意味着无法离线运行。如果你的指令不够明确,它也可能跑题或出戏。

因此现实中常见的模式是混合使用:每个 NPC 的行为逻辑用经典 AI 实现,LLM 对话只留给少数以自由交流为核心的角色。如果你想深入了解,包括人格提示词、记忆系统、如何让角色紧扣游戏世界观,我们写了一篇专门的教程:在 Godot 4 中构建带有记忆和人格的 AI NPCAI NPC 生成器是快速搭建原型的最快方式。

更快的路径:让 AI 原生引擎来写

以上所有内容都是手动路线,理解它很有价值,因为它教会了你这些模式。但手写、接线、调试一个状态机既耗时又费力,而且很多 bug 只有运行游戏时才会暴露。

AI 原生引擎改变的正是这个环节。Summer Engine 兼容 Godot 4,并将 AI 助手直接集成在编辑器内部,它不只是在侧边栏建议代码。它能读取你的场景树、编写 GDScript、接线 NavigationAgent 和检测用的 Area2D、运行游戏、读取运行时错误、并修复问题。你只需用日常语言描述行为:

让骷髅在两点之间巡逻,发现玩家后追击,靠近后攻击。使用导航系统让它能绕过墙壁。

它会生成和上面完全相同的状态机,挂载到真实的敌人场景上,然后按下播放键确认骷髅真的在追击而不是撞墙。这种「写代码、运行游戏、读结果」的循环,正是 AI 助手与能交付可运行行为的 AI 引擎之间的本质区别,因为游戏里大多数 AI 问题都是运行时 bug,而聊天窗口永远看不到它们。

实话实说:免费套餐涵盖构建、测试和导出,足以让你学会这些模式、发布第一个 AI 驱动的原型。付费套餐为日常工作提供更多用量和更强大的模型。如果你想比较在 Godot 工作流中使用 AI 的各种选择,Godot AI 页面有详细说明;模板库提供了已经接好敌人 AI 的起始项目,让你直接修改行为,而不是从零搭建。

从哪里开始

如果你还在学习,就动手搭建第一部分。状态机加 NavigationAgent 几乎能覆盖你将来遇到的所有敌人、伙伴和生物,而且这套模式从单个地精扩展到完整战斗遭遇都游刃有余。

只有当自由对话真正是某个角色的核心玩法时,才考虑第二部分,并且把 LLM 对话控制在少数几个 NPC 上,以保持合理的成本和延迟。

当你想比逐个手打状态更快推进时,用语言描述行为,让引擎来构建和测试。本指南里的这些模式,正是它会生成的代码,所以理解它们能让你更好地引导它——无论你选择哪条路。

Frequently asked questions

如何在 Godot 4 中制作敌人 AI?

搭建一个状态机。创建一个以 CharacterBody2D 或 CharacterBody3D 为根节点的敌人场景,添加一个 NavigationAgent 节点,然后编写脚本,用枚举定义 IDLE(待机)、PATROL(巡逻)、CHASE(追击)、ATTACK(攻击)等状态。每帧检查条件(玩家是否在范围内、是否可见),并切换状态,再执行当前状态对应的行为。使用 NavigationAgent 的 get_next_path_position 来驱动移动,让敌人能绕过障碍物而不是直接撞墙。本指南提供了一个可以直接粘贴使用的追击与攻击脚本。

Godot 有内置 AI 吗?

Godot 4 提供了经典游戏 AI 所需的基础构件,但没有现成的 AI 大脑。它内置了 NavigationServer,包含 NavigationAgent2D 和 NavigationAgent3D 用于寻路,NavigationRegion 节点用于定义可行走区域,射线检测用于视线判断,Area 节点用于检测范围。它没有内置用于决策的状态机或行为树,这部分需要你自己用 GDScript 编写,或者借助插件实现。对于语言模型 AI,Godot 提供了 HTTPRequest 来调用外部模型,但没有内置模型本身。像 Summer Engine 这样兼容 Godot 4 的 AI 原生引擎可以替你写好所有决策逻辑。

如何给 Godot 游戏添加寻路功能?

在 3D 场景中,添加一个 NavigationRegion3D 并在关卡上烘焙导航网格,让 Godot 知道哪里是可行走的地面。给需要移动的角色添加 NavigationAgent3D。在脚本中,调用 set_target_position 设置目标位置,然后每个物理帧读取 get_next_path_position 并朝该位置移动。2D 场景的流程完全相同,使用 NavigationRegion2D 和 NavigationAgent2D 即可。导航代理会自动处理绕过障碍物的路径规划,你的 AI 脚本只需决定目的地,不需要关心路径本身。

我能在 Godot 里做一个像 ChatGPT 一样会说话的 AI NPC 吗?

可以。通过 Godot 的 HTTPRequest 节点,把玩家的消息加上一段描述角色的系统提示词一起发送给语言模型,然后把回复以对话形式展示出来。维护一份历史对话记录,让 NPC 能记住上下文;同时用清晰的指令约束模型,使其保持角色人设、不破坏游戏氛围。需要权衡的是延迟、每条消息的成本,以及必须联网这一前提——这也是大多数游戏只为少数关键角色使用 LLM 对话、而非所有 NPC 都使用的原因。

在 Godot 里做 AI 需要很强的编程能力吗?

制作经典行为 AI 需要你能熟练使用 GDScript:枚举、match 语句和物理处理循环。跟着教程学,一个周末就能掌握。制作 LLM NPC 还需要处理 HTTP 请求和 JSON。如果编程是你的障碍,像 Summer Engine 这样兼容 Godot 4 的 AI 原生引擎允许你用日常语言描述行为,由它来生成状态机和导航代码,并运行游戏验证效果。即便如此,理解这些基本模式依然很有价值,因为这能让你更好地引导它。

Summer Engine 制作 AI 行为是免费的吗?

Summer Engine 提供免费套餐,涵盖游戏的构建、测试和导出,包括编写状态机、导航等 AI 行为代码。付费套餐提供更多用量、更快的响应速度和更强大的模型,对于每天持续开发的项目会更有帮助。如果你只是学习这些模式、或者想发布第一个 AI 驱动的原型,免费套餐已经足够。