Polylines and Paths
Joins, per-point color and thickness.
A polyline is a line drawn with a list of points.
Points
polyline_points_2d(points, closed) draws a PackedVector2Array in the
current style. closed joins the last point back to the first.
extends Node2D
func _process(_delta: float) -> void:
GeomDraw.reset_all_draw_states()
GeomDraw.thickness = 8.0
GeomDraw.color = Color(0.42, 0.85, 1.0)
# An open zigzag path
var zigzag := PackedVector2Array()
zigzag.resize(6)
for i in 6:
zigzag[i] = Vector2(60 + i * 44, 110 + 120 * (i % 2))
GeomDraw.polyline_points_2d(zigzag, false)
# A closed pentagon path
var pentagon := PackedVector2Array()
pentagon.resize(5)
for i in 5:
var angle := -TAU / 4 + i * TAU / 5
pentagon[i] = Vector2(460, 170) + Vector2(cos(angle), sin(angle)) * 70
GeomDraw.polyline_points_2d(pentagon, true)
using Godot;
public partial class PolylinePoints : Node2D
{
public override void _Process(double delta)
{
Geom.Draw.ResetAllDrawStates();
Geom.Draw.Thickness = 8.0f;
Geom.Draw.Color = new Color(0.42f, 0.85f, 1.0f);
// An open zigzag path
var zigzag = new Vector2[6];
for (int i = 0; i < 6; i++)
{
zigzag[i] = new Vector2(60 + i * 44, 110 + 120 * (i % 2));
}
Geom.Draw.PolylinePoints2D(zigzag, false);
// A closed pentagon path
var pentagon = new Vector2[5];
for (int i = 0; i < 5; i++)
{
var angle = -Mathf.Tau / 4 + i * Mathf.Tau / 5;
pentagon[i] = new Vector2(460, 170) + new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * 70;
}
Geom.Draw.PolylinePoints2D(pentagon, true);
}
}

Per-Point Style
For a color or thickness per point, build a GeomPolylinePath and draw it with
polyline_2d(path, closed). add_point_2d_full(position, color, scale) adds
a point with its own color and a thickness scale. The point’s color multiplies
color, and its scale multiplies thickness.
extends Node2D
func _process(_delta: float) -> void:
GeomDraw.reset_all_draw_states()
GeomDraw.thickness = 24.0
GeomDraw.polyline_join = Geom.JOIN_ROUND
var path := GeomPolylinePath.new()
for i in 30:
var u := i / 29.0
var position := Vector2(60 + u * 520, 170 + sin(u * TAU) * 70)
var color := Color(1.0, 0.78, 0.36, u)
path.add_point_2d_full(position, color, u)
GeomDraw.polyline_2d(path, false)
using Godot;
public partial class PolylinePath : Node2D
{
public override void _Process(double delta)
{
Geom.Draw.ResetAllDrawStates();
Geom.Draw.Thickness = 24.0f;
Geom.Draw.PolylineJoin = Geom.PolylineJoin.Round;
var path = Geom.PolylinePath.New();
for (int i = 0; i < 30; i++)
{
var u = i / 29.0f;
var position = new Vector2(60 + u * 520, 170 + Mathf.Sin(u * Mathf.Tau) * 70);
var color = new Color(1.0f, 0.78f, 0.36f, u);
path.AddPoint2DFull(position, color, u);
}
Geom.Draw.Polyline2D(path, false);
}
}

The 3D forms drop the _2d: polyline_points, polyline and add_point_full.
Joins
polyline_join sets how the corners are drawn:
JOIN_SIMPLE | the two segments meet at plain width, so the outside pinches in |
JOIN_MITER | the outside edges extend until they meet, clamped on sharp turns |
JOIN_ROUND | a disc over each corner |
JOIN_BEVEL | the outside of the corner cut off square |
extends Node2D
func _process(_delta: float) -> void:
GeomDraw.reset_all_draw_states()
GeomDraw.thickness = 26.0
GeomDraw.color = Color(0.42, 0.85, 1.0)
var corner := PackedVector2Array()
corner.resize(3)
corner[0] = Vector2(-50, 240)
corner[1] = Vector2(0, 110)
corner[2] = Vector2(50, 240)
GeomDraw.transform_2d = Transform2D(0.0, Vector2(90, 0))
GeomDraw.polyline_join = Geom.JOIN_SIMPLE
GeomDraw.polyline_points_2d(corner, false)
GeomDraw.transform_2d = Transform2D(0.0, Vector2(240, 0))
GeomDraw.polyline_join = Geom.JOIN_MITER
GeomDraw.polyline_points_2d(corner, false)
GeomDraw.transform_2d = Transform2D(0.0, Vector2(390, 0))
GeomDraw.polyline_join = Geom.JOIN_ROUND
GeomDraw.polyline_points_2d(corner, false)
GeomDraw.transform_2d = Transform2D(0.0, Vector2(540, 0))
GeomDraw.polyline_join = Geom.JOIN_BEVEL
GeomDraw.polyline_points_2d(corner, false)
using Godot;
public partial class PolylineJoins : Node2D
{
public override void _Process(double delta)
{
Geom.Draw.ResetAllDrawStates();
Geom.Draw.Thickness = 26.0f;
Geom.Draw.Color = new Color(0.42f, 0.85f, 1.0f);
var corner = new Vector2[3];
corner[0] = new Vector2(-50, 240);
corner[1] = new Vector2(0, 110);
corner[2] = new Vector2(50, 240);
Geom.Draw.Transform2D = new Transform2D(0.0f, new Vector2(90, 0));
Geom.Draw.PolylineJoin = Geom.PolylineJoin.Simple;
Geom.Draw.PolylinePoints2D(corner, false);
Geom.Draw.Transform2D = new Transform2D(0.0f, new Vector2(240, 0));
Geom.Draw.PolylineJoin = Geom.PolylineJoin.Miter;
Geom.Draw.PolylinePoints2D(corner, false);
Geom.Draw.Transform2D = new Transform2D(0.0f, new Vector2(390, 0));
Geom.Draw.PolylineJoin = Geom.PolylineJoin.Round;
Geom.Draw.PolylinePoints2D(corner, false);
Geom.Draw.Transform2D = new Transform2D(0.0f, new Vector2(540, 0));
Geom.Draw.PolylineJoin = Geom.PolylineJoin.Bevel;
Geom.Draw.PolylinePoints2D(corner, false);
}
}

JOIN_ROUNDdraws its discs as separate shapes, so a translucent polyline is darker where a disc overlaps the line.
Limits
dashed and fill are not supported on a polyline.