Getting Started with AI Game Development in Godot on macOS

I’m currently building a mobile bubble game in Godot on a MacBook with an Apple M3 Pro chip, and one thing surprised me early on: how little setup Godot needs on a Mac. No installer, no account, no license server. You download one app, open it, and you’re making a game a few minutes later.
In this guide I’ll show you how to set up Godot 4 on macOS and build a small test game with a simple AI enemy that notices you when you come close and chases you. It’s the same kind of logic that sits behind many enemies in real games, and it’s a quick way to check that everything on your Mac works.
What “AI” means in this guide
In game development, “AI” usually doesn’t mean chatbots or machine learning. It means the code that makes characters decide what to do: when to chase, when to stop, when to give up. Our enemy will follow two simple rules:
- If the player is within its sight range, chase the player.
- If the player is too far away, stop and wait.
Simple rules like these, combined well, are what make enemies feel alive.
Why Godot on a Mac?
- Free and open source: Godot is released under the MIT license. There are no fees or royalties, even for commercial games.
- Small and fast: the editor is a single app of a few hundred megabytes and opens in seconds.
- Native on every Mac: the official macOS download is a universal app, so it runs natively on both Apple Silicon (M1, M2, M3, M4) and Intel Macs.
- Easy to learn: GDScript, Godot’s own language, reads a lot like Python.
Step 1: Install Godot on macOS
- Go to the official website, godotengine.org/download/macos, and download the latest stable Godot 4 version. Choose the standard version. You only need the .NET version if you want to write C#.
- Open the downloaded ZIP file and drag Godot.app into your Applications folder.
- Open Godot from Applications. If macOS shows a security warning, open System Settings → Privacy & Security, scroll down, and click Open Anyway.
Step 2: Create a new project
- In the Project Manager, click Create.
- Name the project
AI_Chase_Testand choose a folder for it. - Leave the renderer on Forward+ (or choose Mobile if you plan to make a phone game) and click Create & Edit.
- In the Scene dock on the left, click 2D Scene. This creates a
Node2Droot node. Double-click it and rename it toMain. - Press Command + S and save the scene as
main.tscn.
Step 3: Create the player
- Right-click
Main, choose Add Child Node, search forCharacterBody2D, and add it. Rename it toPlayer. - Add a
Sprite2Das a child ofPlayer. Dragicon.svg(the Godot logo) from the FileSystem dock into the sprite’s Texture property in the Inspector. - To colour it, open Visibility in the Inspector and set Modulate to blue.
- Add a
CollisionShape2Das another child ofPlayer. In the Inspector, set Shape to New RectangleShape2D and resize it to cover the sprite. - Select
Player, click the Attach Script button (the scroll icon with a plus), name itplayer.gd, and replace the code with this:
extends CharacterBody2D
@export var speed := 300.0
func _physics_process(_delta: float) -> void:
# The built-in "ui_" actions use the arrow keys (and a gamepad) by default.
var direction := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = direction * speed
move_and_slide()
@export makes speed appear in the Inspector, so you can tweak it without touching the code. move_and_slide() moves the body using its velocity and handles collisions for you.
Step 4: Create the AI enemy
- Add another
CharacterBody2DtoMainand rename it toEnemy. - Give it a
Sprite2Dwith the sameicon.svgtexture, and aCollisionShape2Dwith aRectangleShape2D. You don’t need to colour it; the script below does that. - In the 2D view, drag the
Enemyto the other side of the screen, away from the player. - Attach a script named
enemy.gdtoEnemyand use this code:
extends CharacterBody2D
@export var speed := 150.0
@export var sight_range := 400.0 # how far the enemy can "see", in pixels
@export var stop_distance := 40.0 # stop when this close, instead of pushing into the player
@onready var player: Node2D = $"../Player"
@onready var sprite: Sprite2D = $Sprite2D
func _physics_process(_delta: float) -> void:
var to_player := player.global_position - global_position
var distance := to_player.length()
if distance < sight_range and distance > stop_distance:
# Chase: move straight toward the player.
velocity = to_player.normalized() * speed
sprite.modulate = Color.RED
else:
# Wait: the player is too far away (or already caught).
velocity = Vector2.ZERO
sprite.modulate = Color(1.0, 0.6, 0.6)
move_and_slide()
This is a tiny state machine with two states, chase and wait. The colour shows you which state the enemy is in: bright red while chasing, pale red while waiting.
Step 5: Run the test game
- Click the Run Project button (the play icon at the top right), or press Command + B.
- Godot asks you to choose a main scene. Click Select Current to use
main.tscn. - Move the blue player with the arrow keys. Walk toward the enemy: when you’re within 400 pixels, it turns bright red and starts chasing you. Run far enough away and it stops.
If both of those things happen, your Godot setup on macOS is working: input, physics, and scripting are all fine.
Optional: move with WASD too
The built-in ui_ actions only include the arrow keys. To add WASD:
- Open Project → Project Settings and go to the Input Map tab.
- Add four new actions:
move_left,move_right,move_upandmove_down. - Click the + next to each action and press the key for it: A, D, W and S. You can add the arrow keys to the same actions too.
- In
player.gd, change the line to:Input.get_vector("move_left", "move_right", "move_up", "move_down")
Common problems
- “Invalid access to property ‘global_position’ on a base object of type ‘null instance’”: the enemy can’t find the player. Check that the player node is named exactly
Playerand that it’s a sibling ofEnemyunderMain. - The player doesn’t move: click inside the game window first, so it has keyboard focus.
- The enemy never chases: it may be placed further than 400 pixels away. Increase
sight_rangein the Inspector.
Where to go next
- NavigationAgent2D lets the enemy find its way around walls instead of walking straight at you.
- More states, such as patrol, search and flee, make enemies more interesting. A simple
matchstatement on a state variable is enough to start. - Raycasts (
RayCast2D) let an enemy check whether a wall blocks its view before it starts chasing.
Godot on a Mac is one of the easiest ways to start making games. Build small tests like this one, change one value at a time, and watch what happens. That’s how most game AI is actually made.
