# How to Make AI in Godot 4: A Step-by-Step Guide (2026)

> A practical guide to building AI in Godot 4, from enemy state machines and pathfinding to LLM-driven NPCs, with copy-paste GDScript and a faster AI-assisted path.

- URL: https://www.summerengine.com/blog/how-to-make-ai-in-godot
- Published: 2026-06-06T00:00:00.000Z
- Author: Summer Team
- Tags: Godot, AI, GDScript, Tutorial

Ask "how to make AI in Godot" and you will get two completely different answers depending on what you meant, because the same phrase covers two unrelated jobs.

One is classic game AI: the goblin that spots you, chases you around a pillar, and swings when it gets close. This is decision logic plus movement, and it has been the bread and butter of game development for decades.

The other is language-model AI: the shopkeeper you can actually talk to in your own words, who answers in character. This is new, it sends text to a model over the internet, and it solves a different problem.

Most games need the first kind for almost everything and reach for the second only for a handful of talking characters. This guide covers both, in order, with GDScript you can paste into Godot 4. At the end it shows how an AI-native engine writes this code for you and tests it by running the game, which is the part tutorials usually skip.

## Part 1: Classic Game AI (the kind you need most)

When a designer says an enemy "has good AI," they almost never mean it runs a neural network. They mean it makes sensible decisions: it notices the player, picks a reasonable action, and changes its mind when the situation changes. In code, that is a state machine.

A state machine is a list of states (idle, patrol, chase, attack) and the rules for moving between them. It is the single most useful pattern in game AI, and Godot 4 has everything you need to build one.

### Step 1: Set up the enemy scene

Create a new scene with a `CharacterBody2D` as the root (use `CharacterBody3D` for 3D, the logic is identical). Add these children:

- A `Sprite2D` or `AnimatedSprite2D` so you can see it
- A `CollisionShape2D` so it has a body
- An `Area2D` with its own `CollisionShape2D`, sized larger than the enemy, to act as a detection radius
- A `NavigationAgent2D` so the enemy can route around walls

The detection `Area2D` is how the enemy "sees." When the player enters it, the enemy knows to react.

### Step 2: Write the state machine

Attach this script to the root. It defines four states and switches between them based on distance to the player.

```gdscript
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
```

Two things make this work. The `match` statement on `state` keeps each behavior isolated, so adding a new state later does not tangle the others. And the `Area2D` body-entered and body-exited signals (connected from the editor's Node tab) flip the enemy between aware and unaware without polling every frame.

Put your player in the `player` group (select it, Node tab, Groups, add "player") so the detection check finds it.

### Step 3: Add pathfinding so the enemy walks around walls

The script above uses `NavigationAgent2D`, but the agent needs a map of where the floor is. Add a `NavigationRegion2D` to your level scene and give it a `NavigationPolygon` that covers the walkable ground, with holes cut out for walls. Godot routes the agent through it automatically.

The key idea: your AI script decides the destination (`nav.target_position = player.global_position`), and the navigation system decides the route. You never write pathfinding math yourself. `get_next_path_position()` hands you the next waypoint, and you move toward it.

In 3D, the flow is the same with `NavigationRegion3D` and `NavigationAgent3D`. You bake a navigation mesh over the level geometry instead of drawing a polygon, but the script pattern does not change.

### Step 4: Add line of sight (optional but worth it)

A detection radius alone means the enemy sees through walls. To fix that, add a `RayCast2D` and check whether the ray to the player hits anything before committing to a chase.

```gdscript
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
```

Gate your `IDLE -> CHASE` transition on `can_see_player()` and the enemy now needs an actual sightline, which feels far more fair and intelligent to the player.

That is a complete, shippable enemy AI: it detects, chases around obstacles, respects walls for sight, and attacks in range. Patrol routes, fleeing at low health, and group tactics are all just more states and more transitions on the same skeleton.

## Part 2: LLM-Driven AI (talking NPCs)

The second meaning of "AI in Godot" is an NPC you can converse with freely. This is a different mechanism entirely. Instead of a state machine, you send text to a language model and turn the reply into dialogue.

Godot 4 has no built-in model, but it has `HTTPRequest`, which is all you need to call one.

### Step 1: Send a message to a model

Add an `HTTPRequest` node and a script that posts the player's message plus a short character description to a model API.

```gdscript
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)
```

### Step 2: Give the NPC memory

A model with no memory restarts every conversation. To make the blacksmith remember you, keep a running list of past exchanges and include a short summary in each request. Store it on the NPC, append each turn, and when it gets long, ask the model to summarize the old turns into a sentence or two so the prompt does not grow without bound.

### Step 3: Know the tradeoffs before you commit

LLM dialogue is powerful but it is not free. Every message costs money, takes a moment to come back over the network, and needs an internet connection, which means it cannot run offline. It can also drift off-topic or out of character if your instructions are loose.

This is why the realistic pattern is hybrid: classic AI for behavior on every NPC, and LLM dialogue reserved for a few characters where open conversation is the point. If you want the full version of this, including personality prompts, memory systems, and keeping characters grounded in game state, we wrote a dedicated walkthrough on [building AI NPCs with memory and personality in Godot 4](/blog/how-to-build-ai-npcs-in-godot). The [AI NPC generator](/ai-npc-generator) is the fastest way to scaffold one.

## The faster path: let an AI-native engine write it

Everything above is the manual route, and it is worth understanding because it teaches you the patterns. But writing, wiring, and debugging a state machine by hand is slow, and the bugs only show up when you run the game.

This is where an AI-native engine changes the work. [Summer Engine](/ai-game-maker) is compatible with Godot 4 and builds the AI assistant into the editor itself, so it does not just suggest code in a side panel. It reads your scene tree, writes the GDScript, wires up the `NavigationAgent` and detection `Area2D`, runs the game, reads the runtime errors, and fixes them. You describe the behavior in plain language:

> Make the skeleton patrol between two points, chase the player when it sees them, and attack when close. Use navigation so it goes around walls.

It produces the same state machine you saw above, attached to a real enemy scene, then presses play to confirm the skeleton actually chases instead of walking into a wall. That write, play, read loop is the difference between an AI that hands you a code snippet and one that delivers working behavior, because most AI bugs in a game are runtime bugs a chat window never sees.

The honest version: the free tier covers building, testing, and exporting, which is enough to learn the patterns and ship a first AI-driven prototype. Paid plans add more usage and stronger models for daily work. If you want to compare the options for AI in a Godot workflow, the [Godot AI](/godot-ai) page lays them out, and the [template library](/templates) gives you starting projects with enemies already wired so you are editing behavior instead of building it from zero.

## Where to start

If you are learning, build Part 1 by hand. A state machine and a `NavigationAgent` will carry you through nearly every enemy, companion, and creature you will ever need, and the pattern scales from a single goblin to a full combat encounter.

Reach for Part 2 only when open conversation is genuinely the point of a character, and keep it to a few NPCs so cost and latency stay sane.

And when you want to move faster than typing each state by hand, describe the behavior and let the engine build and test it for you. The patterns in this guide are exactly what it writes, so understanding them makes you better at directing it, whichever route you take.

---

## Machine-readable resources

- Site index for agents: https://www.summerengine.com/llms.txt
- Full inlined content: https://www.summerengine.com/llms-full.txt
- Porting catalog: https://www.summerengine.com/llms-porting.txt
- Structured catalog: https://www.summerengine.com/agent-catalog.json
- Sitemap: https://www.summerengine.com/sitemap.xml
- Developer resources: https://www.summerengine.com/docs