Video summary
Juiced Up First Person Character Controller Tutorial - Godot 3D FPS
Main summary
Key takeaways
Technological concepts & tutorial flow (Godot 3D FPS Character Controller)
Goal
Build a first-person character controller from scratch in Godot 3D FPS, with an emphasis on game feel / game juice.
Core features planned/implemented
- Head bob
- Inertia / air control smoothing
- Movement/velocity improvements
- Camera field-of-view (FOV) changes with speed
- Mouse look with proper pivot handling
- Sprint support
- Performance-friendly prototyping environment
Scene setup & character scaffolding
World and ground block
- Creates a new 3D scene (“world”).
- Uses CSG Box + collision shape for a ground block (noted as good for prototyping).
Player character base
- Uses CharacterBody3D (subclass/placeholder from the Godot template) for the player.
- Adds a visual mesh (“bean shape”) and generates a simplified convex collision sibling.
- Turning off mesh visibility shows the simplified collision has fewer vertices, improving performance.
Lighting and environment
- Adds WorldEnvironment and DirectionalLight to simulate sunlight.
Camera and pivot handling
- Adds a Camera as a child of a dedicated pivot node.
- Notes rotation problems if a pivot node is not used.
- References Godot documentation on pivot/rotation behavior.
Base movement, jumping, and physics logic
Starting point
- Begins from a default character controller template (includes movement + jump).
- Designed to be usable for both FP and TP.
Key constants and settings
- Uses constants:
speedjump_velocity- gravity (explicitly set to 9.8)
Physics_process responsibilities
- On Space:
- sets upward velocity for jumping
- Each tick:
- applies gravity when not on the floor
- uses
move_and_slideto move and resolve collisions
Floor movement and direction
- Builds a Vector2 movement input, then converts to a Vector3 direction relative to the facing direction.
- Sets horizontal velocity using:
- direction ×
speed
- direction ×
Noted friction mistake
- An attempted “friction / smooth stop” accidentally results in setting velocity to 0 instantly.
- This is linked to a GitHub thread.
Input mapping & mouse capture
Input map configuration
- Creates a custom Input Map in Project Settings, defining actions and bindings.
Cursor capture fix
- Sets mouse mode to captured inside a ready() function so the player can look and move.
Mouse look implementation
- Uses unhandled input:
- handles mouse motion events
- rotates:
- Head yaw (Y-axis) from mouse X movement
- Camera pitch (X-axis) from mouse Y movement
- Uses separate rotation axes to avoid rotation-order issues.
- Explains that pitch/yaw behavior can feel unintuitive because mouse movement is translated into different rotation axes.
Camera clamping + basic playable map
Rotation limits
- Uses
clampto restrict camera rotation to a safe min/max to prevent flipping or extreme angles.
Environment building
- Creates a more interesting level by placing multiple CSG boxes with different materials/colors rather than using only a single white box.
Movement direction fix (face head, not body)
- Fixes movement direction so it follows the head direction (the look component).
- Previously, movement direction followed the CharacterBody facing.
“Game juice” additions
1) Head Bob (using sine wave)
Implements head bob via a sine wave.
- Variables/constants:
- Bob frequency (how often bobbing occurs)
- Bob amplitude (strength of bobbing)
- T_bob accumulator advanced every physics tick
- Update logic:
T_bobadvances using delta time and player speed- bobbing applies only when on the floor and walking, using an
is_on_floor()-based factor cast to float
- Camera transform:
- Vertical bob:
sin(T_bob * Bob_frequency) * Bob_amplitude - Optional horizontal sway: uses a cosine component
- x offset based on
cos(T_bob * Bob_frequency / 2) * Bob_amplitude
- x offset based on
- Vertical bob:
- Result: more realistic stepping motion while walking.
2) Sprint + bob scaling by speed
- Adds sprinting via:
- walk_speed
- sprint_speed
- In physics processing:
- sets active
speedbased on whether Shift is pressed
- sets active
- Benefit:
- head bob frequency/intensity naturally adapts since it ties to speed.
3) Inertia / better air control (no instant stop midair)
Addresses the issue where releasing input midair stops horizontal motion abruptly.
- Adds inertia using lerp while in the air:
- full control on the floor
- in air, interpolate current horizontal velocity toward desired velocity using
lerp - tune responsiveness using
deltascaling (example:delta * 3)
- Also improves stopping behavior by ramping deceleration rather than instantly cutting velocity.
4) Speed-based FOV change
Improves motion feel with dynamic FOV.
- Constants:
- base_fov
- fov_change
- Target FOV:
target_fov = base_fov + fov_change * velocity_clamped
- Uses velocity clamping to prevent extreme FOV:
- minimum around 0.5
- maximum around running_speed * 2
- Smooths FOV changes:
- uses
lerpeach physics tickcamera_fov = lerp(current_fov, target_fov, delta_scaled)
- uses
Review / guide / tutorial takeaways
- This serves as a complete tutorial for building a usable Godot FPS controller and enhancing it with game feel mechanics.
- Key analysis points:
- Why camera rotation needs a pivot node
- A known mistake where “friction” accidentally becomes instant velocity zeroing
- Tuning inertia and FOV behavior using clamping and lerp interpolation
Main speakers / sources
- Main speaker: The YouTube channel creator (narrator/instructor)
- Sources referenced:
- Godot documentation (pivot/rotation behavior; code snippet mentioned)
- Godot GitHub thread (about the friction/velocity-to-zero behavior)
Rate this summary
Your feedback will help improve summaries.
Improve this summary
Reprocess with a stronger model when the summary feels incomplete or inaccurate.
Translate summary in another language
Ask questions to this video
Chat for follow-up questions, clarifications, and source-backed answers.