Skip to content
Back to skills

Camera Rigs

ASecurity

Camera rigs: Camera2D follow with limits, first-person head, SpringArm3D third-person, top-down, FOV.

  • 77 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 16, 2026
ai-agentsgoshellnodespringawstesting

Works with

  • claude code
  • cursor
  • cli
  • mcp

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 16, 2026

npx -y skills add SummerEngine/summer --skill camera-rigs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Camera Rigs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Camera Rigs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/summerengine-camera-rigs-summer/badge)](https://www.skillsdirectory.com/skills/summerengine-camera-rigs-summer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: camera-rigs
description: "Camera rigs: Camera2D follow with limits, first-person head, SpringArm3D third-person, top-down, FOV."
license: MIT
compatibility: [Cursor, Claude Code, Codex, Windsurf, Gemini, OpenCode]
category: scene-and-project
user-invocable: false
allowed-tools: Read Grep summer_get_scene_tree summer_inspect_node summer_add_node summer_set_prop summer_batch summer_save_scene summer_screenshot summer_play summer_stop summer_get_diagnostics
paths: ["**/*.tscn", "**/*.gd"]
---

# Camera Rigs

One rule above all: exactly ONE camera is active. In 3D that is the single
`Camera3D` with `current = true`; two current cameras = flicker or the wrong
view, and a scene with no current camera renders nothing in the game. In 2D a
`Camera2D` is active when `enabled = true` (the default) and it is in the tree;
with several enabled cameras, call `make_current()` on the one you want.

Trigger phrases: "black screen on play", "camera shows past the level edge",
"jerky follow", "wrong FOV", "I need a top-down / isometric / orbit camera".

Ops use engine variant strings (`"Vector3(0, 5, 10)"`), never JSON objects
(`{x: 0, y: 5, z: 10}` fails). Every mutation names its scene: pass the exact
`scenePath` (e.g. `res://main.tscn`). One `summer_batch` per rig saves the scene
once; the examples below use it.

## 2D follow camera

Add the `Camera2D` as a CHILD of the player so it follows for free, then smooth
it and clamp it to the level.

```
summer_batch(scenePath="res://main.tscn", ops=[
  {"op": "AddNode", "parent": "./Player", "type": "Camera2D", "name": "Camera"},
  {"op": "SetProp", "path": "./Player/Camera", "key": "position_smoothing_enabled", "value": true},
  {"op": "SetProp", "path": "./Player/Camera", "key": "position_smoothing_speed", "value": 6.0},
  {"op": "SetProp", "path": "./Player/Camera", "key": "limit_left", "value": 0},
  {"op": "SetProp", "path": "./Player/Camera", "key": "limit_right", "value": 1920},
  {"op": "SetProp", "path": "./Player/Camera", "key": "limit_top", "value": 0},
  {"op": "SetProp", "path": "./Player/Camera", "key": "limit_bottom", "value": 1080}
])
```

- Smoothing speed 5-8 feels responsive; higher = tighter, lower = drifty.
- Set limits to the actual level bounds (the numbers above are placeholders).
  `limit_smoothing_enabled = true` avoids a hard stop at the edge.
- Zoom `Vector2(2, 2)` zooms IN (bigger), `Vector2(0.5, 0.5)` zooms OUT (top-down).

## 2D top-down camera

Same as above minus the platformer edge-lock urgency. Zoom out to show the field
(`Vector2(0.5, 0.5)`). Keep it centered on the player; no vertical bias.

## 3D first-person camera

Camera is a child of a `Head` node on the player. Body yaws, Head pitches. See
the `character-movement` skill (its 3D movement reference: `summer_docs_read` id `skill/character-movement/references/movement-3d.md`) or
`fps-controller` for the look script. FOV 70-75, near 0.05.

```
summer_batch(scenePath="res://main.tscn", ops=[
  {"op": "AddNode", "parent": "./Player/Head", "type": "Camera3D", "name": "Camera"},
  {"op": "SetProp", "path": "./Player/Head/Camera", "key": "fov", "value": 72.0},
  {"op": "SetProp", "path": "./Player/Head/Camera", "key": "near", "value": 0.05},
  {"op": "SetProp", "path": "./Player/Head/Camera", "key": "current", "value": true}
])
```

## 3D third-person camera (spring arm)

The `SpringArm3D` pushes the camera in when a wall is behind the player, so it
never clips through geometry. This is the correct third-person rig - do not just
park a Camera3D behind the player.

```
summer_batch(scenePath="res://main.tscn", ops=[
  {"op": "AddNode", "parent": "./Player", "type": "SpringArm3D", "name": "SpringArm"},
  {"op": "SetProp", "path": "./Player/SpringArm", "key": "position", "value": "Vector3(0, 2, 0)"},
  {"op": "SetProp", "path": "./Player/SpringArm", "key": "spring_length", "value": 4.5},
  {"op": "SetProp", "path": "./Player/SpringArm", "key": "collision_mask", "value": 2},
  {"op": "AddNode", "parent": "./Player/SpringArm", "type": "Camera3D", "name": "Camera"},
  {"op": "SetProp", "path": "./Player/SpringArm/Camera", "key": "current", "value": true}
])
```

Set `collision_mask` to the LEVEL layer only. If it includes the player layer the
arm collapses to length 0 and you see inside the character (a controller script
can also call `add_excluded_object(get_rid())` on the arm).

## Orthographic top-down 3D (twin-stick, strategy, isometric)

```
summer_batch(scenePath="res://main.tscn", ops=[
  {"op": "SetProp", "path": "./Camera", "key": "projection", "value": 1},
  {"op": "SetProp", "path": "./Camera", "key": "size", "value": 20.0},
  {"op": "SetProp", "path": "./Camera", "key": "position", "value": "Vector3(0, 20, 0)"},
  {"op": "SetProp", "path": "./Camera", "key": "rotation_degrees", "value": "Vector3(-90, 0, 0)"}
])
```

`projection = 1` is orthogonal. `size` is the vertical world units shown - bigger
= more zoomed out. For isometric, rotate ~(-30, 45, 0) instead of straight down.

## FOV guidance

- 60-75: most 3D games. 90+: fast FPS (feels faster, more peripheral).
- Under 40 or over 110 distorts. Never animate FOV wildly; a small kick (+8 on
  sprint, tweened back) reads as speed.

## Verify

A camera is only proven by a frame. After the rig is in, `summer_play`, then
`summer_screenshot` with `target: "game"`, then `summer_stop`; or save frames
from a `RunVerification` probe while the player moves (see
`playtesting-a-feature`). An editor `viewport` screenshot shows the editor's
camera, not the game's.

## Troubleshooting

| Symptom | Cause | Fix |
|---------|-------|-----|
| Black screen | No current/enabled camera | 3D: `current = true` on exactly one; 2D: one enabled Camera2D in the tree |
| Camera inside geometry | Spawned inside a wall/player | Move it out; spring arm for 3P |
| Jerky follow | Smoothing off/too slow | Enable smoothing, speed 6-10 |
| Shows past level edge | No 2D limits | Set `limit_*` to level bounds |
| Wrong facing (3D) | rotation.y off | y: 0 = forward, 180 = backward |
| Everything tiny/huge (ortho) | `size` wrong | Tune `size`, not `position.y` |

<!-- shell-commands: generated from the operation catalog by npm run generate:registry; do not edit by hand -->
## From a shell

No Summer MCP tools in this session? Run each one as a command; when `summer --version` is missing or below 4.0, use `npx -y summer-engine@4.3.0` in place of `summer`. Fields are flags in kebab-case (`--scene-path res://main.tscn`) or one `--input '<json>'`, and `summer ops describe <op>` prints the exact input. The `summer-cli` skill has the rest.

| In this skill | Command |
|---|---|
| `summer_docs_read` | `summer docs read` |
| `summer_add_node` | `summer engine add-node` |
| `summer_batch` | `summer engine batch` |
| `summer_get_diagnostics` | `summer engine get-diagnostics` |
| `summer_get_scene_tree` | `summer engine get-scene-tree` |
| `summer_inspect_node` | `summer engine inspect-node` |
| `summer_play` | `summer engine play` |
| `summer_save_scene` | `summer engine save-scene` |
| `summer_screenshot` | `summer engine screenshot` |
| `summer_set_prop` | `summer engine set-prop` |
| `summer_stop` | `summer engine stop` |
<!-- /shell-commands -->

Files in this skill

  • SKILL.md7 KB
  • resource.yaml705 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.