Opens in a new tab

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

  1. 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#.
  2. Open the downloaded ZIP file and drag Godot.app into your Applications folder.
  3. 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

  1. In the Project Manager, click Create.
  2. Name the project AI_Chase_Test and choose a folder for it.
  3. Leave the renderer on Forward+ (or choose Mobile if you plan to make a phone game) and click Create & Edit.
  4. In the Scene dock on the left, click 2D Scene. This creates a Node2D root node. Double-click it and rename it to Main.
  5. Press Command + S and save the scene as main.tscn.

Step 3: Create the player

  1. Right-click Main, choose Add Child Node, search for CharacterBody2D, and add it. Rename it to Player.
  2. Add a Sprite2D as a child of Player. Drag icon.svg (the Godot logo) from the FileSystem dock into the sprite’s Texture property in the Inspector.
  3. To colour it, open Visibility in the Inspector and set Modulate to blue.
  4. Add a CollisionShape2D as another child of Player. In the Inspector, set Shape to New RectangleShape2D and resize it to cover the sprite.
  5. Select Player, click the Attach Script button (the scroll icon with a plus), name it player.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

  1. Add another CharacterBody2D to Main and rename it to Enemy.
  2. Give it a Sprite2D with the same icon.svg texture, and a CollisionShape2D with a RectangleShape2D. You don’t need to colour it; the script below does that.
  3. In the 2D view, drag the Enemy to the other side of the screen, away from the player.
  4. Attach a script named enemy.gd to Enemy and 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

  1. Click the Run Project button (the play icon at the top right), or press Command + B.
  2. Godot asks you to choose a main scene. Click Select Current to use main.tscn.
  3. 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:

  1. Open Project → Project Settings and go to the Input Map tab.
  2. Add four new actions: move_left, move_right, move_up and move_down.
  3. 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.
  4. 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 Player and that it’s a sibling of Enemy under Main.
  • 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_range in 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 match statement 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.