Traffic Jam!


Devlog: Visual Waypoint System for My Crazy Taxi Clone in Godot

The Problem

Working on my Crazy Taxi clone in Godot, I needed a way to see the paths my AI traffic would follow. I had a basic setup with a parent node holding Marker3D waypoints, but I couldn’t see how they connected in the editor. This made designing routes and spotting issues a pain. I wanted a clear, editor-only view using @tool to make path creation and debugging easier.

Attempt 1: No Line3D

I hunted for a Line3D node, thinking it’d be perfect for drawing 3D paths. Turns out, Godot doesn’t have one, so I had to rethink my approach.

Attempt 2: Editor Plugin

I tried building a custom editor plugin to draw lines in the 3D viewport:

func _forward_3d_draw_over_viewport(overlay):
    for node in EditorInterface.get_selection().get_selected_nodes():
        if node.has_method("get_waypoints"):
            _draw_waypoint_lines(overlay, node)

It worked, sorta, but it was a hassle to set up and only showed lines when I selected the waypoint system.

Solution: Path3D

Then it hit me—Godot’s Path3D with Curve3D was exactly what I needed. It’s built-in, simple, and shows paths right in the editor:

@tool
extends Node3D
@export var update_path: bool = false : set = _update_path_from_waypoints
func _build_path():
    var curve = Curve3D.new()
    for waypoint in waypoints:
        curve.add_point(to_local(waypoint.global_position))
    if loop_path:
        curve.add_point(to_local(waypoints[0].global_position))
    path_node.curve = curve

Better Visualization

To make the paths pop, I added a CSGPolygon3D for a thick, cyan tube along the path:

@export var show_path_mesh: bool = true
@export var path_thickness: float = 0.1
func _update_path_mesh():
    path_mesh = CSGPolygon3D.new()
    path_mesh.mode = CSGPolygon3D.MODE_PATH
    path_mesh.path_node = path_node.get_path()
    var polygon = PackedVector2Array()
    for i in 8:
        var angle = i * 2.0 * PI / 8
        polygon.append(Vector2(cos(angle), sin(angle)) * path_thickness)
    path_mesh.polygon = polygon

How It Changed My Workflow

This setup made designing levels so much better. I can drop Marker3D waypoints around the map, toggle update_path to see the full path instantly, move waypoints to tweak the route, and spot problems like weird turns right away. The AI Traffic is programming to turn using linear interpolation so the fact that the paths above are straight lines do not matter. They will do tight turns, but that seems more arcadey. Besides, the traffic is not the main feature, it's only meant to be an obstacle in the game. 

AI Traffic Integration

The AI traffic use this system to navigate. They can find the closest waypoint:

func get_closest_index(position: Vector3) -> int:
    var closest_index := -1
    var closest_dist := INF
    for i in waypoints.size():
        var dist = position.distance_to(waypoints[i].global_position)
        if dist < closest_dist:
            closest_dist = dist
            closest_index = i
    return closest_index

If a taxi gets knocked off course, it finds the nearest waypoint, jumps back on the path, and keeps going without starting over.

This Path3D system made building AI paths for my Crazy Taxi clone way easier, using Godot’s own tools to keep things clean and manageable.

Files

index.zip 110 MB
12 days ago

Get Uber Munch

Leave a comment

Log in with itch.io to leave a comment.