【Godot】CharacterBody2D vs RigidBody2D vs StaticBody2D - Choosing the Right 2D Physics Body in Godot Engine

Created: 2025-12-08Last updated: 2025-12-16

Learn the features, characteristics, performance, and practical use cases of Godot Engine's main 2D physics bodies—CharacterBody2D, RigidBody2D, and StaticBody2D—with code examples.

When developing 2D games in Godot Engine, choosing the right node for giving objects "physical behavior" is crucial. The three main physics body nodes—CharacterBody2D, RigidBody2D, and StaticBody2D—each have different design philosophies and purposes. Using them correctly directly affects game performance, ease of control, and bug prevention.

This article explains the basic definitions, characteristics, and appropriate use cases for these three physics body nodes with concrete code examples.


The Three Physics Bodies: Fundamental Concepts

All three nodes inherit from CollisionObject2D and can have collision shapes, but the "mover" of each is completely different.

Node NameControl AuthorityPhysics Engine InfluenceInteraction with Other ObjectsPrimary Uses
StaticBody2DNone (fixed)Not affectedBecomes a "wall" that blocks collisionsGround, walls, immobile obstacles
RigidBody2DPhysics EngineAffected (fully simulated)Moved by collisions and moves othersBalls, boxes, physics puzzle elements
CharacterBody2DDeveloper's CodePartially affected (collision detection)Blocks collisions but generally isn't movedPlayers, enemies, moving platforms

1. StaticBody2D: The Immovable Reference Point

StaticBody2D is the "immovable presence" in the physics world. It never moves due to gravity or external forces. Its role is to provide "walls" and "floors" for other objects to collide with.

  • Main Properties: constant_linear_velocity, constant_angular_velocity
  • Key Point: It should generally not be moved, but if you need to move it, consider using AnimatableBody2D. This is a special static body that moves in sync with animations.

2. RigidBody2D: The Embodiment of Physics Laws

RigidBody2D is the star of the physics engine. Once placed in the world, it moves autonomously according to physics laws like gravity, friction, and collisions. Developers control it indirectly by applying forces and impulses rather than directly manipulating position.

Practical Code Example: Throwing Objects with RigidBody2D

extends RigidBody2D

@export var throw_force: float = 500.0

func throw(direction: Vector2):
    # Reset existing motion
    linear_velocity = Vector2.ZERO
    angular_velocity = 0.0

    # Apply impulse in specified direction
    apply_central_impulse(direction.normalized() * throw_force)

Performance Considerations

RigidBody2D is computationally expensive. In scenes where hundreds of RigidBody2D collide with each other, performance can significantly degrade. Enabling the sleep (can_sleep) setting to skip physics calculations when objects are stationary is very important.


3. CharacterBody2D: Precise Control Through Code

CharacterBody2D is the most specialized and important node, designed for developers to completely control character movement. While utilizing the physics engine's collision detection capability, movement itself is determined through code via the move_and_slide() method.

Practical Code Example: More Practical Player Control

In Godot 4, velocity became a built-in property. Below is more practical code that considers jump input buffering (Coyote Time) and jump buffering.

extends CharacterBody2D

@export var speed: float = 300.0
@export var jump_velocity: float = -450.0
@export var gravity: float = 980.0

# Timers for coyote time and jump buffer
# CoyoteTimer: wait_time = 0.1, one_shot = true
# JumpBufferTimer: wait_time = 0.15, one_shot = true
@onready var coyote_timer: Timer = $CoyoteTimer
@onready var jump_buffer_timer: Timer = $JumpBufferTimer

var was_on_floor: bool = false

func _physics_process(delta: float) -> void:
    # 1. Apply gravity
    if not is_on_floor():
        velocity.y += gravity * delta

    # 2. Buffer jump input
    if Input.is_action_just_pressed("jump"):
        jump_buffer_timer.start()

    # 3. Execute jump
    # Jump if on floor or during coyote time, and jump is buffered
    if (is_on_floor() or not coyote_timer.is_stopped()) and not jump_buffer_timer.is_stopped():
        velocity.y = jump_velocity
        jump_buffer_timer.stop()

    # 4. Horizontal movement
    var direction: float = Input.get_axis("move_left", "move_right")
    velocity.x = direction * speed

    # 5. Movement and collision detection
    var was_on_floor_before = is_on_floor()
    move_and_slide()

    # 6. Start coyote timer the moment leaving the floor
    if not is_on_floor() and was_on_floor_before:
        coyote_timer.start()

This code implements important techniques that make platform games "feel good to control," beyond just basic movement.


Common Mistakes and Best Practices

Common MistakeWhy It's a ProblemBest Practice
Using RigidBody2D for player characterPhysics simulation inertia and rebound prevent responsive input-driven movement.Always use CharacterBody2D for players and enemies.
Directly modifying CharacterBody2D's positionCollision detection via move_and_slide() doesn't work, causing clipping through walls.Always update velocity and call move_and_slide().
Performing physics calculations in _process(delta)_physics_process(delta) is called at a fixed frame rate, ensuring physics calculation stability.Write all physics-related processing in _physics_process(delta).
Using overly complex CollisionShape2DMore polygon vertices increase collision detection computational cost.Use simple shapes (RectangleShape2D, CircleShape2D) whenever possible.

Tips for Choosing the Right Node

When uncertain about node selection, answer these questions:

  1. Does the object move?
    • No: Choose StaticBody2D. (e.g., walls, ground)
  2. Do you want the object's movement completely governed by physics laws (gravity, collisions, forces)?
    • Yes: Choose RigidBody2D. (e.g., balls, boxes)
  3. Do you want to precisely control the object's movement through player input or AI logic?
    • Yes: Choose CharacterBody2D. (e.g., players, enemies)

Summary

Godot Engine's 2D physics bodies have clearly defined roles:

  • StaticBody2D: Immovable environmental elements.
  • RigidBody2D: Objects completely governed by physics laws.
  • CharacterBody2D: Characters precisely controlled through code.

By understanding these differences and choosing the appropriate node based on your game object's nature, you can develop games that behave more smoothly and as intended.