A production-ready cinematic camera system for Godot 4.x.
Drop it into any 3D project and get smooth tracking, scripted camera moves, rail followers, profile presets, shot sequencing, and screen shake -- all from GDScript with a clean, chainable API.
- Tracking camera -- orbit-style framing around one or two targets with configurable distance, height, angle, tilt, and smoothing
- Scripted moves -- smooth tween-based transitions between positions with
move_to(), instant cuts withhold_at() - Camera profiles -- reusable
CameraProfileresources with built-in presets (close-up, medium shot, wide shot, dramatic low, bird's eye, over-the-shoulder, telephoto) - Rail follower -- drive the camera along a
Path3Dwith look-at targeting, speed control, easing curves, looping, and pause/resume - Shot sequencer -- chain shots into timed sequences with per-shot callbacks, transitions, and hold times
- Screen shake -- noise-based trauma system with quadratic falloff for organic-feeling impacts
- Fully exported -- all parameters exposed to the Inspector; works in
@toolmode for editor previews
- Copy the
addons/cinematic_camera/folder into your project'saddons/directory. - The scripts use
class_nameregistration, so Godot will pick them up automatically -- no plugin activation required. - Add a
CinematicCameranode to your scene (it extendsCamera3D).
your_project/
addons/
cinematic_camera/
cinematic_camera.gd
camera_profile.gd
rail_follower.gd
shot_sequence.gd
plugin.cfg
@onready var camera: CinematicCamera = $CinematicCamera
@onready var player: Node3D = $Player
func _ready() -> void:
camera.track(player)# Built-in presets
camera.apply_profile(CameraProfile.close_up())
camera.apply_profile(CameraProfile.dramatic_low())
# Custom profile
var profile := CameraProfile.create("my_shot", 8.0, 3.0, 50.0, 15.0, 5.0)
camera.apply_profile(profile)# Smooth move over 3 seconds
var tween := camera.move_to(Vector3(10, 5, 10), player.global_position, 40.0, 3.0)
await tween.finished
# Instant cut
camera.hold_at(Vector3(0, 2, 5), player.global_position, 55.0, true)
# Resume tracking after a scripted move
camera.resume_tracking()camera.shake(0.6, 0.4) # intensity 0-1, duration in seconds
await camera.shake_completedvar seq := ShotSequence.new(camera)
seq.add_shot({
"position": Vector3(-5, 3, 8),
"look_at": Vector3.ZERO,
"fov": 35.0,
"duration": 2.0,
"transition": ShotSequence.Transition.SMOOTH,
"hold": 1.0,
})
seq.add_shot({
"position": Vector3(0, 10, 0.1),
"look_at": Vector3.ZERO,
"fov": 60.0,
"duration": 1.5,
"transition": ShotSequence.Transition.CUT,
})
seq.play()
await seq.sequence_completedvar rail := RailFollower.new()
add_child(rail)
rail.path = $CameraRail # a Path3D with a Curve3D
rail.camera = $CinematicCamera
rail.look_at_target = $Player
rail.speed = 5.0
rail.start()
await rail.rail_completedExtends Camera3D. The main camera node.
| Method | Description |
|---|---|
hold_at(pos, look_at, fov, cut) |
Position the camera at a world position. cut=true teleports instantly. |
move_to(pos, look_at, fov, duration) -> Tween |
Smooth tween to a position. Returns the Tween for chaining/awaiting. |
set_framing(distance, height, fov, angle, tilt) |
Configure orbit framing parameters. |
track(target, secondary?) |
Set tracking target(s) and enter tracking state. |
resume_tracking() |
Resume tracking after a scripted move. |
shake(intensity, duration) |
Trigger screen shake. Stacks additively. |
apply_profile(profile) |
Apply a CameraProfile resource. |
get_state() -> State |
Returns IDLE, TRACKING, or SCRIPTED. |
| Signal | Description |
|---|---|
move_completed |
Emitted when a move_to tween finishes. |
shake_completed |
Emitted when shake finishes. |
tracking_changed(primary, secondary) |
Emitted when targets change. |
| Export | Default | Description |
|---|---|---|
default_fov |
70.0 |
Default field of view. |
smoothing_speed |
5.0 |
Position interpolation speed. |
look_smoothing_speed |
8.0 |
Look-at interpolation speed. |
framing_distance |
10.0 |
Orbit distance from target. |
framing_height |
2.0 |
Height offset from target. |
framing_angle |
0.0 |
Horizontal orbit angle (degrees). |
framing_tilt |
0.0 |
Vertical tilt (degrees). |
max_trauma |
1.0 |
Maximum shake trauma. |
trauma_decay |
1.5 |
Trauma decay rate per second. |
Extends Resource. A reusable set of framing parameters.
| Static Method | Distance | Height | FOV | Angle | Tilt |
|---|---|---|---|---|---|
close_up() |
2.5 | 1.5 | 35 | 0 | 0 |
medium_shot() |
6.0 | 2.0 | 55 | 0 | 0 |
wide_shot() |
18.0 | 4.0 | 70 | 0 | 5 |
dramatic_low() |
5.0 | -2.0 | 40 | 15 | -15 |
birds_eye() |
25.0 | 20.0 | 60 | 0 | 60 |
over_the_shoulder() |
3.0 | 1.8 | 50 | 25 | 5 |
telephoto() |
40.0 | 3.0 | 20 | 0 | 2 |
Use CameraProfile.create(name, distance, height, fov, angle, tilt, smoothing) to build custom profiles.
Extends Node3D. Drives a camera along a Path3D.
| Method | Description |
|---|---|
start() |
Begin following the rail. |
pause() / resume() |
Pause and resume movement. |
stop() |
Stop and reset to the beginning. |
seek(ratio) |
Jump to a position (0.0 to 1.0). |
get_progress_ratio() -> float |
Current progress along the rail. |
| Signal | Description |
|---|---|
rail_started |
Emitted when the rail begins. |
rail_completed |
Emitted when the camera reaches the end. |
progress_updated(ratio) |
Emitted each frame with current progress. |
| Export | Default | Description |
|---|---|---|
path |
null |
The Path3D to follow. |
camera |
null |
The CinematicCamera to drive. |
look_at_target |
null |
Optional node to look at while on the rail. |
speed |
5.0 |
Movement speed (units/sec). |
loop |
false |
Loop back to start on completion. |
autoplay |
false |
Start automatically on _ready(). |
ease_curve |
null |
Optional Curve for easing. |
Extends RefCounted. Chains shots into a timed sequence.
| Method | Description |
|---|---|
add_shot(dict) -> ShotSequence |
Append a shot. Returns self for chaining. |
play(from_index?) |
Start playing. |
pause() / unpause() |
Pause and resume. |
skip() |
Skip to the next shot. |
stop() / reset() |
Stop and reset. |
size() -> int |
Number of shots. |
| Signal | Description |
|---|---|
sequence_completed |
Emitted when all shots finish. |
shot_changed(index) |
Emitted when a new shot begins. |
Shot dictionary keys:
| Key | Type | Required | Description |
|---|---|---|---|
position |
Vector3 |
Yes | Camera position. |
look_at |
Vector3 |
Yes | Look-at target. |
fov |
float |
No | Field of view (0 = use default). |
duration |
float |
No | Transition time in seconds (default 1.0). |
transition |
Transition |
No | CUT or SMOOTH (default SMOOTH). |
hold |
float |
No | Seconds to hold before next shot. |
profile |
CameraProfile |
No | Apply this profile on enter. |
on_enter |
Callable |
No | Called when shot begins. |
on_exit |
Callable |
No | Called when shot ends. |
- Open the project in Godot 4.x.
- Open
examples/demo_scene.tscn. - Press F5 (or set it as the main scene).
- Press Space to advance through demo steps. Press R to reset.
MIT License. See LICENSE.
Built by Colossus Forge Studios.