Godot 2d Movement

作者 gamedev-skillsd4b0e35550c5無授權條款1.3K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫11 天前更新

Implement 2D kinematic character movement in Godot 4.7 with CharacterBody2D and move_and_slide(): platformer run/jump with gravity, top-down 8-direction motion, slope handling, and reading collisions. Use when coding a 2D player or enemy controller, a platformer or top-down character, or fixing move_and_slide()/ is_on_floor() behavior in a .tscn with a CharacterBody2D.

AI 產生的概覽

使用 CharacterBody2D 與 move_and_slide() 在 Godot 4.7 中實作 2D 角色移動。

功能
此技能提供在 Godot 4.7 中使用 CharacterBody2D 與無參數的 move_and_slide() 建立 2D 運動學角色控制器的說明與 GDScript 模式。內容涵蓋平台跳躍的跑動/跳躍與重力、俯視 8 方向移動、斜坡處理、土狼時間以及讀取滑動碰撞,並列出常見陷阱,例如 3.x 簽章已被移除、將速度乘以 delta 等。它也指向一個包含更多控制器配方的參考檔案。
適用情境
適用於撰寫會移動和碰撞的 2D 玩家或敵人控制器,例如平台遊戲或俯視角色。也適用於 move_and_slide() 似乎沒有作用、角色穿過地板或 is_on_floor() 始終為 false 的情況。
執行需求
需要 Godot 4.7 與 GDScript;不附帶指令碼,只有說明和一份參考文件。跳躍和移動方向等輸入動作需在專案的輸入對應中設定。

Godot 2D Movement (4.x)

Build responsive 2D character controllers with CharacterBody2D and the argument-less move_and_slide(). Targets Godot 4.7.

When to use

  • Use when scripting a 2D player/enemy that moves and collides: platformer (gravity + jump) or top-down (free 8-direction), slope walking, or wall/floor detection.
  • Use when move_and_slide() "does nothing", the character sinks through floors, or is_on_floor() is always false.

When not to use: dynamic rigid bodies, areas, raycasts, collision layers → godot-physics; tile-based levels → godot-tilemap; full platformer game template → the platformer genre skill; engine-agnostic feel tuning → physics-tuning.

Core workflow

  1. Use CharacterBody2D with a CollisionShape2D child. It is script-driven: it does not fall or react to forces on its own.
  2. Set the velocity property, then call move_and_slide() (no arguments in 4.x). The method reads velocity, moves the body, slides along surfaces, and updates velocity to reflect what actually happened.
  3. Do it in _physics_process(delta) — move_and_slide() uses the physics step's delta internally, so do not multiply velocity by delta yourself.
  4. Platformer: add gravity to velocity.y each tick, jump by setting velocity.y negative when is_on_floor().
  5. Top-down: build a direction from input and scale by speed; set motion_mode = MOTION_MODE_FLOATING so there is no "floor/wall" distinction.
  6. Read results with is_on_floor(), is_on_wall(), get_wall_normal(), and get_slide_collision(i) after the call.

Patterns

1. Platformer controller (gravity, jump, slopes)

gdscript
extends CharacterBody2D
@export var speed := 200.0@export var jump_velocity := -400.0@export var gravity := 1200.0          # pixels/sec^2 (tune to taste)
func _physics_process(delta: float) -> void:    # Apply gravity while airborne.    if not is_on_floor():        velocity.y += gravity * delta
    # Jump only when grounded (Input action set in Project Settings > Input Map).    if Input.is_action_just_pressed("jump") and is_on_floor():        velocity.y = jump_velocity
    # Horizontal input: -1, 0, or 1.    var dir := Input.get_axis("move_left", "move_right")    if dir != 0.0:        velocity.x = dir * speed    else:        velocity.x = move_toward(velocity.x, 0.0, speed)   # decelerate to a stop
    move_and_slide()   # 4.x: no arguments; uses and updates `velocity`

2. Top-down 8-direction movement

gdscript
extends CharacterBody2D
@export var speed := 220.0
func _ready() -> void:    motion_mode = CharacterBody2D.MOTION_MODE_FLOATING  # no floor/ceiling concept
func _physics_process(_delta: float) -> void:    # get_vector returns a normalized-ish Vector2 from four input actions.    var input := Input.get_vector("move_left", "move_right", "move_up", "move_down")    velocity = input * speed    move_and_slide()

3. Reading slide collisions after moving

gdscript
func _physics_process(delta: float) -> void:    # ... set velocity ...    move_and_slide()    for i in get_slide_collision_count():        var c := get_slide_collision(i)        var other := c.get_collider()        if other and other.is_in_group("enemies"):            take_damage(1)        # touched an enemy while moving

4. Coyote time (forgiving jump just after leaving a ledge)

gdscript
@export var coyote_time := 0.1var _coyote := 0.0
func _physics_process(delta: float) -> void:    if not is_on_floor():        velocity.y += gravity * delta        _coyote -= delta    else:        _coyote = coyote_time
    if Input.is_action_just_pressed("jump") and _coyote > 0.0:        velocity.y = jump_velocity        _coyote = 0.0    # ... horizontal input + move_and_slide() ...

Pitfalls

  • 3.x signature is gone. move_and_slide(velocity) (returning the new velocity) was removed. In 4.x set the velocity property and call move_and_slide() with no args. move_and_slide(velocity, Vector2.UP) will not parse.
  • Multiplying velocity by delta. move_and_slide() already accounts for the physics delta. Setting velocity = dir * speed * delta makes the body crawl.
  • Movement in _process instead of _physics_process causes frame-rate-dependent, jittery motion. Always move in _physics_process.
  • is_on_floor() always false when up_direction is wrong (default Vector2.UP), there is no CollisionShape2D, or you never called move_and_slide() this frame.
  • Sinking through floors usually means the collision shape is missing/zero-sized, the floor body is on a layer this body's mask doesn't include, or you moved the body via position += instead of velocity + move_and_slide().
  • Slope slipping while idle: keep floor_stop_on_slope = true (default) and set a floor_snap_length so the body sticks to downward slopes.

References

  • For one-way platforms, moving platforms, jump buffering, variable jump height, and move_and_collide() (manual collision response), read references/controller-recipes.md.

Related skills

  • godot-physics — collision layers/masks, areas, raycasts, rigid bodies.
  • godot-tilemap — building the levels this character walks on.
  • godot-animation — driving sprite/skeletal animation from movement state.
  • camera-systems — follow camera, deadzone, and look-ahead that track this character.
  • platformer / input-systems — full genre template and rebindable input.

來源與署名

來源:gamedev-skills/awesome-gamedev-agent-skills位於skills/godot/godot-2d-movement提交d4b0e35

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架