Skip to content
Loadout

Fix

Godot 4 move_and_slide and delta

Answer

In Godot 4 set velocity, then call move_and_slide() with no arguments. Do not multiply horizontal velocity by delta. move_and_slide() applies the timestep. Gravity is the exception: velocity.y += gravity * delta before the call. Run movement in _physics_process, not _process.

  • Godot 4.7.2-stable (18 August 2026)
  • GDScript 2.0

Last verified 2026-10-15

Agents still multiply velocity by delta, pass velocity into move_and_slide, or run the move in _process. The Godot 4 pack is written to stop that paste. It is pinned to Godot 4.7.2-stable (18 August 2026) and GDScript 2.0. KinematicBody2D, yield, and export var are the rename page, /fixes/godot-3-code-in-godot-4. setget, Tween.new(), and @tool are /fixes/godot-4-setget-tweens-and-tool. This page is the movement section of the same rules file.

Bodies are CharacterBody2D and CharacterBody3D. They own a velocity property, Vector2 or Vector3. Set velocity, then call move_and_slide() with no arguments. Do not pass the velocity, an up vector, or a delta into move_and_slide. Do not multiply horizontal velocity by delta. move_and_slide() applies the timestep. Gravity is the exception: velocity.y += gravity * delta before the call. Applying delta to horizontal velocity and then calling move_and_slide() runs the timestep twice.

Read input with Input.get_vector or Input.is_action_pressed, using actions from the Input Map. Do not hardcode key scancodes in gameplay code. Run movement in _physics_process, not _process. The sample in the pack extends CharacterBody2D, exports speed as a float with a default, caches the sprite with @onready, reads Input.get_vector of the ui_left, ui_right, ui_up, and ui_down actions, assigns velocity = input * speed, and calls move_and_slide() with no arguments inside _physics_process. It does not multiply by delta.

Give @export a type and a default. It is for designer-facing values only. Use @onready to cache child nodes. Do not call get_node() every frame. Put gameplay code on the node that owns the behavior. The done checklist is the Godot editor shows no parser errors on the edited scripts, nothing from the ban list appears in the diff, and you said whether the scene was actually run.

Last verified 2026-10-15. doc-verified; GDScript sample parsed by Godot 4.7.2 headless (--check-only), with a Godot 3 control script correctly rejected.

Godot 4 pack — GDScript 2.0 rules that refuse Godot 3 APIs.

doc-verified; GDScript sample parsed by Godot 4.7.2 headless (--check-only), with a Godot 3 control script correctly rejected

Sample from the pack

The movement sample in the Godot 4 rules file.

extends CharacterBody2D

@export var speed: float = 200.0
@onready var sprite: Sprite2D = $Sprite2D

func _physics_process(_delta: float) -> void:
    var input := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    velocity = input * speed
    move_and_slide()

Sources in the pack

Questions

Should Godot 4 movement multiply velocity by delta?
In Godot 4 set velocity, then call move_and_slide() with no arguments. Do not multiply horizontal velocity by delta. move_and_slide() applies the timestep. Gravity is the exception: velocity.y += gravity * delta before the call. Run movement in _physics_process, not _process.
What arguments does move_and_slide take in Godot 4?
None. Set velocity, then call move_and_slide() with no arguments. Do not pass the velocity, an up vector, or a delta into move_and_slide.
Should Godot 4 movement run in _process or _physics_process?
Run movement in _physics_process, not _process. Read input with Input.get_vector or Input.is_action_pressed using actions from the Input Map. Do not hardcode key scancodes.
When was this Godot 4 movement rule last checked?
Last verified 2026-10-15. doc-verified; GDScript sample parsed by Godot 4.7.2 headless (--check-only), with a Godot 3 control script correctly rejected.