mcpField
G
godot-3d-gameplay

godot-3d-gameplay

github.com/pbzonaDevelopment242 installsUpdated 14w ago
Repository

About godot-3d-gameplay

A skill for implementing 3D gameplay in Godot while preserving a project's architecture. It covers physics, cameras, lighting, and rendering, with inspection and in-game verification guiding design choices.

Key features

  1. 01Inspect project settings and existing scenes
  2. 02Choose physics bodies for gameplay roles
  3. 03Build typed player controllers with physics ticks
  4. 04Configure camera rigs and input actions
  5. 05Tune environment lighting for readability
  6. 06Test gameplay, visuals, and performance

Use cases

  1. 01Adding a player controller to an existing Godot project
  2. 02Integrating camera collision with level geometry
  3. 03Tuning lighting for a target renderer
  4. 04Verifying movement across slopes and platforms

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/pbzona/godot-skills --skill godot-3d-gameplay

After installing, type/godot-3d-gameplayin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
controllers-and-cameras.md
environments-and-lighting.md
physics-testing-and-debugging.md

Details

From the project README

Godot 3D Gameplay

Implement 3D gameplay as a coordinated physics, camera, and rendering system. Preserve the project's existing architecture and tune from observed behavior rather than replacing working systems with a generic controller.

Inspect Before Editing

Do not write scenes, scripts, or project settings until this inspection is complete.

  1. Find project.godot and confirm the project root. Read config/features, the rendering method, physics tick rate, display settings, 3D physics layer names, and existing Input Map actions.
  2. Run the project's established Godot executable with --version when available. Match APIs to that exact Godot 4.x release; do not silently upgrade the project or its resource formats.
  3. Inspect representative .tscn, .gd, and imported 3D assets. Record scene ownership, node naming, typed GDScript style, signal style, groups, autoloads, folder layout, and whether node references use exported nodes, unique names, or paths.
  4. Inspect the current player, camera, level, environment, collision layers and masks, model scale, applied transforms, and input bindings. Check whether meshes or resources are shared before editing them.
  5. Identify the target renderer and hardware. A Forward+ desktop scene, a Mobile-renderer game, and a Compatibility project require different lighting and environment choices.
  6. Establish a runnable baseline and note existing warnings. Do not attribute pre-existing errors to the requested change.

If the editor version, project feature tag, and requested API disagree, stop and resolve the version mismatch before authoring resources.

Choose the Smallest Suitable Design

  • Use CharacterBody3D for script-directed avatars that need floor, wall, slope, and moving-platform behavior.
  • Use AnimatableBody3D for script- or animation-driven platforms that should carry characters.
  • Use RigidBody3D for bodies whose motion should come from forces and impulses. Do not drive one like a character by overwriting its transform every frame.
  • Keep collision, gameplay state, visuals, and camera pivots in separate child branches when they change for different reasons.
  • Use Input Map actions, not physical key constants, so keyboard and gamepad bindings can share gameplay code.
  • Use a SpringArm3D camera rig when level geometry can move between the subject and camera.
  • Start with one WorldEnvironment and one primary light. Add post-processing and extra shadowed lights only after the base image reads clearly.

Implementation Workflow

  1. Define observable behavior: movement reference frame, top speed, acceleration, air control, slope limit, jump rules, camera range, camera collision, and visual target.
  2. Build or adapt a reusable player scene. Align the capsule or other simple collider to the feet, keep the visual model transform local, and leave the root at identity for clean instancing.
  3. Confirm action names and deadzones in the Input Map. Reuse project actions where their semantics match.
  4. Implement physics in _physics_process(delta). Treat CharacterBody3D.velocity as units per second and call move_and_slide() once per physics tick.
  5. Implement look events in _unhandled_input(event) unless the project has an input router. Keep yaw and pitch on separate pivots and exclude the player collider from the spring arm.
  6. Establish the environment and lighting for readability first. Tune sky or background, ambient contribution, key-light direction, exposure, fog, and shadows as one composition.
  7. Test controller, camera, and lighting together in representative geometry before polishing animation or effects.

Typed Controller Example

Adapt names and structure to the inspected project. Assign view_camera in the Inspector and define move_left, move_right, move_forward, move_back, and jump actions.

extends CharacterBody3D

@export_range(0.1, 30.0, 0.1) var move_speed: float = 7.0
@export_range(0.1, 100.0, 0.1) var ground_acceleration: float = 28.0
@export_range(0.1, 100.0, 0.1) var air_acceleration: float = 9.0
@export_range(0.1, 30.0, 0.1) var jump_velocity: float = 8.5
@export var view_camera: Camera3D

var gravity: float = float(
    ProjectSettings.get_setting("physics/3d/default_gravity", 9.8)
)

func _ready() -> void:
    assert(is_instance_valid(view_camera), "Assign the movement camera")

func _physics_process(delta: float) -> void:
    var move_input: Vector2 = Input.get_vector(
        &"move_left", &"move_right", &"move_forward", &"move_back"
    )

    # Camera +Z points backward, matching the positive Y returned for move_back.
    var camera_back: Vector3 = view_camera.global_transform.basis.z
    var camera_right: Vector3 = view_camera.global_transform.basis.x
    camera_back.y = 0.0
    camera_right.y = 0.0
    camera_back = camera_back.normalized()
    camera_right = camera_right.normalized()

    var wish_direction: Vector3 = (
        camera_right * move_input.x + camera_back * move_input.y
    ).limit_length(1.0)
    var target_velocity: Vector3 = wish_direction * move_speed
    var response: float = (
        ground_acceleration if is_on_floor() else air_acceleration
    )

    velocity.x = move_toward(velocity.x, target_velocity.x, response * delta)
    velocity.z = move_toward(velocity.z, target_velocity.z, response * delta)

    if is_on_floor():
        if velocity.y < 0.0:
            velocity.y = 0.0
        if Input.is_action_just_pressed(&"jump"):
            velocity.y = jump_velocity
    else:
        velocity.y -= gravity * delta

    move_and_slide()

Tune floor_max_angle, floor_snap_length, floor_stop_on_slope, platform layers, and platform_on_leave on the body rather than recreating those behaviors ad hoc. Add coyote time, jump buffering, sprinting, or root motion only when the game specification calls for them.

Verification

Run the project's own checks first, then perform all applicable steps:

  • Import and parse with the matching editor. If the project supports headless validation, use <godot> --headless --path <project> --editor --quit and inspect the full output.
  • Run the player scene and at least one integrated level. Confirm there is exactly one active gameplay camera.
  • Test start, stop, reverse, diagonal input, no-input deceleration, jump press versus hold, ceiling contact, ledges, stairs, shallow and over-limit slopes, walls, corners, and moving platforms.
  • Rotate the camera through its full range. Check movement orientation, pitch clamps, camera collision, recovery after an obstruction, near-clip intersections, and mouse capture release.
  • Test at low and high rendered frame rates while keeping physics behavior stable. Look for frame-dependent camera smoothing and animation code.
  • Use visible collision shapes and the remote scene tree to verify collider alignment, layers, masks, active environment, and runtime transforms.
  • Compare representative dark, bright, indoor, and outdoor views. Check exposure, silhouettes, shadow acne, peter-panning, fog readability, and material response.
  • Profile on target-class hardware before retaining expensive shadows, volumetric effects, screen-space effects, or many dynamic lights.
  • Re-run the baseline and report changed files, settings, tests, and any device or visual checks that could not be performed.

Pitfalls

  • Multiplying CharacterBody3D.velocity by delta before move_and_slide(); the body expects velocity, not per-frame displacement.
  • Moving a physics body by position or global_transform and then expecting slide collisions or floor state to be reliable.
  • Using the camera's pitched forward vector directly, which adds unwanted vertical movement.
  • Parenting the camera directly to animated visual bones or rotating the entire player to aim the camera.
  • Giving detailed render meshes equally detailed collision, or using non-uniformly scaled collision shapes.
  • Reading is_on_floor() as a predictive query; it describes the previous move_and_slide() result.
  • Hard-coding keys, collision layer numbers, node paths, or gravity when project settings already define them.
  • Enabling every environment effect before checking renderer support and GPU cost.
  • Editing a shared Environment, material, mesh, or shape resource when only one scene instance should change.
  • Treating a headless parse as visual verification; cameras, materials, shadows, and fog still require rendered inspection.

References

Comments

Markdown supported