Physics2DDirectBodyState in Godot 4: it is PhysicsDirectBodyState2D now

By Eduardo Orellana · Updated

Physics2DDirectBodyState is called PhysicsDirectBodyState2D in Godot 4, the "2D" moving to the end like the rest of the physics classes. In a Godot 4 project, a variable typed Physics2DDirectBodyState fails to parse with Could not find type "Physics2DDirectBodyState" in the current scope.

AppImage, x86_64. Ubuntu 22.04, Debian 12, Fedora 39 or newer.

Intel or AMD Chromebook, with Linux turned on.

Download for macOSDownload for Windows

What Godot is checking

GDScript resolves every type annotation when the script loads. Physics2DDirectBodyState is not a class in Godot 4, so the analyzer stops with Could not find type and none of the script runs.

The converter carries Physics2DDirectBodyState to PhysicsDirectBodyState2D. It is what a RigidBody2D's _integrate_forces(state) receives: set linear_velocity on it, or read get_contact_count(), to control the body safely inside the physics step.

Reproduce it

A Godot 3 variable typed Physics2DDirectBodyState, in a Godot 4 project.

extends Node

var state: Physics2DDirectBodyState

func _ready():
	print(state)

What Godot 4.7.2 prints

Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

SCRIPT ERROR: Parse Error: Could not find type "Physics2DDirectBodyState" in the current scope.
   at: GDScript::reload (res://answers/physics2ddirectbodystate-in-godot-4/repro.gd:3)
ERROR: Failed to load script "res://answers/physics2ddirectbodystate-in-godot-4/repro.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript_resource_format.cpp:46)

Fix it

A RigidBody2D whose _integrate_forces() caps its speed. get_class() prints the physics server's own subclass of it, which is what the engine hands you.

extends RigidBody2D

var reported := false

func _ready() -> void:
	linear_velocity = Vector2(900, 0)

func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
	state.linear_velocity = state.linear_velocity.limit_length(300)
	if not reported:
		reported = true
		print(state.get_class(), " speed capped to ", state.linear_velocity.length())

What the fixed script prints

Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

GodotPhysicsDirectBodyState2D speed capped to 300.0

Verified on Godot 4.7.2

Both scripts on this page were run headless on Godot 4.7.2 (4.7.2.stable.mono.official.ed1daf0bf) on 18 October 2026, and the output above is what Godot printed, unedited.

Where the check lives in Godot's source: [renames_map_3_to_4.cpp line 1565, Physics2DDirectBodyState to PhysicsDirectBodyState2D](https://github.com/godotengine/godot/blob/4.7.2-stable/editor/project_upgrade/renames_map_3_to_4.cpp#L1565), [PhysicsDirectBodyState2D class reference](https://github.com/godotengine/godot/blob/4.7.2-stable/doc/classes/PhysicsDirectBodyState2D.xml).

Questions

Why change velocity in _integrate_forces() and not _physics_process()?
Setting it on the state inside the step avoids fighting the solver, which overwrites velocity set from outside.
What is the 3D class?
PhysicsDirectBodyState3D, Godot 3's PhysicsDirectBodyState.