mcpField
C
camera-systems

camera-systems

github.com/gamedev-skills開発5.4k8.1k 回インストール1 日前に更新
リポジトリ

camera-systems について

2D・3Dゲームのカメラ構築を支援する、エンジン非依存のスキルです。滑らかな追従や境界制限、衝突回避、ジッターやクリッピングへの対処を扱います。

主な機能

  1. 01フレームレート非依存の追従
  2. 02デッドゾーン、先読み、境界制限
  3. 03三人称視点の旋回と衝突回避
  4. 04一人称視点と複数対象のフレーミング
  5. 05カメラシェイク用オフセット

活用シーン

  1. 01範囲制限付きの2D追従カメラ構築
  2. 02壁を避ける3D旋回カメラの作成
  3. 03フレームレート差によるジッターや急な動きの軽減
  4. 04複数対象の撮影やシェイクの追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill camera-systems

インストール後、Claude Code で/camera-systemsを入力して読み込まれたか確認します。

同梱ファイルreferences/follow-and-framing.md

詳細

カメラシステム

カメラはプレイヤーの窓です。カメラワークが悪いと、優れたゲームもひどく感じられてしまいます。このスキルでは、エンジンに依存しないカメラ技法(スムーズな追従、デッドゾーン、先読み、境界のクランプ、衝突判定付きの三人称オービット、一人称視点のルック、多数のターゲットのフレーミング)を扱い、各エンジンのカメラノードまたはリグに適用します。

使用する場面

  • 2Dカメラでプレイヤーを滑らかに追従したり、レベル内に収めたり、プレイヤーの動きを先読みしたり、小さな動き(デッドゾーン)を無視したりする場合に使用します。
  • 3Dの三人称オービットカメラ(マウス/スティックによる視点操作、衝突時の押し込み)や一人称視点のルックコントローラーを構築するとき、または複数のターゲットを一度にフレーミングするときに使用します。
  • カメラの揺れ、急な移動、酔いやすさ、またはレベルの端の外側が映る問題を修正するときに使用します。

使用しない場面: 画面揺れやインパクト演出の強さとトリガーには、game-feelを使用します(このスキルは、それらが使う揺れオフセットのフックを公開します)。エンジン固有のカメラノード/コンポーネントの設定には、godot-3d-essentials(Camera3D、環境)またはエンジンのスキルを使用します。プレイヤーの移動そのものには、エンジンの移動スキル(godot-2d-movement)を使用します。多数のカメラ/レンダーターゲットのパフォーマンスについては、performance-optimizationを参照してください。

基本的なワークフロー

  1. カメラの役割を決めます。 プラットフォーマー(ジャンプを先読みし、危険を見渡す)、トップダウン(デッドゾーンを使って中央に配置)、三人称(オービット+衝突判定)、一人称(視点操作のみ)。ジャンルによってルールが決まります。
  2. フレームレートに依存しない方法で滑らかに追従させます。 固定のlerp(a, b, 0.1)ではなく、指数平滑化またはスプリング(SmoothDamp)を使ってカメラをターゲットに近づけます。この0.1はフレームごとの値なので、フレームレートによって結果が変わります。
  3. デッドゾーンを追加します。 ターゲットのわずかな動きでカメラがずれないようにし、ターゲットがボックス/ゾーンから出たときだけ追従させます。動きの激しいゲームでの吐き気を防げます。
  4. 先読みでアクションを先導します。 カメラのターゲットを移動方向または向いている方向へオフセットし、急に振り回されないように滑らかに出入りさせます。
  5. レベルの境界内にクランプします。 カメラがプレイ可能エリアの外側を映さないようにします。平滑化と組み合わせれば、境界で滑らかに停止します。
  6. 3Dでは視点操作と衝突判定を分離します。 リグ上のヨー/ピッチでオービットさせ、ジオメトリに遮られたときはスプリングアーム/レイでカメラを手前に引き寄せます。ピッチには上限と下限を設定します。
  7. ターゲットの移動後にカメラを更新します。 1フレームの遅れによる揺れを避けるため、後段の更新ステップ(移動と物理演算の解決後)で追従させます。
  8. フレームレートを低くしたときと高くしたときの両方でターゲットを動かし、角や壁、レベルの端でも確認します。 揺れや境界の外側が見える問題がなく、滑らかに停止することを確かめます。確認した内容を報告します。

パターン

1. Godot 2Dの組み込み追従:平滑化+境界(まずは独自実装しない)
# Godot 4.7 Camera2D. Engine-provided smoothing + hard limits + drag margins.
@onready var cam := $Camera2D
func _ready() -> void:
    cam.make_current()
    cam.position_smoothing_enabled = true
    cam.position_smoothing_speed = 6.0           # higher = snappier; lower = floatier
    cam.limit_left = 0; cam.limit_top = 0        # clamp to the level rect (pixels)
    cam.limit_right = level_width; cam.limit_bottom = level_height
    cam.drag_horizontal_enabled = true           # built-in deadzone via drag margins
2. フレームレートに依存しない滑らかな追従(独自実装する場合)
# RIGHT: exponential smoothing — same feel at any FPS. `rate` ~ 5..12.
func _follow(dt: float) -> void:
    var t := 1.0 - exp(-rate * dt)               # converges correctly regardless of dt
    global_position = global_position.lerp(target.global_position, t)
# WRONG: global_position = global_position.lerp(target.global_position, 0.1)
#        → faster smoothing at higher FPS; different feel on every machine.
# Unity 6.3 LTS: Vector3.SmoothDamp(transform.position, target.position, ref vel, smoothTime) in
# LateUpdate gives the same spring behavior with built-in frame-rate correction.
3. デッドゾーン+先読み(プレイヤーの動きを先導し、細かな揺れを無視)
# Camera only chases once the target leaves the deadzone box, then aims AHEAD of motion.
func _camera_target(dt: float) -> Vector2:
    var to := target.global_position - _focus
    var dz := deadzone_half_extents                  # e.g. Vector2(48, 32)
    # Only move the focus by the overflow beyond the deadzone (per axis).
    _focus.x += clampf(absf(to.x) - dz.x, 0, INF) * signf(to.x)
    _focus.y += clampf(absf(to.y) - dz.y, 0, INF) * signf(to.y)
    var lead := target.velocity.normalized() * look_ahead_dist    # aim ahead of travel
    return _focus + lead
4. 衝突時の押し込み機能付き三人称3Dオービット
# Godot 4.7. Yaw/pitch a pivot; a SpringArm3D auto-pulls the camera in when blocked.
func _unhandled_input(e):
    if e is InputEventMouseMotion:
        _yaw -= e.relative.x * sensitivity
        _pitch = clampf(_pitch - e.relative.y * sensitivity, -1.2, 0.4)   # clamp pitch!
func _process(_dt):
    pivot.rotation = Vector3(_pitch, _yaw, 0)
    # $SpringArm3D handles wall collision: set spring_length + collision_mask; the child
    # Camera3D slides in automatically. RIGHT: spring arm. WRONG: camera clips through walls.
# Unity 6.3 LTS: a Cinemachine 3 CinemachineCamera (namespace Unity.Cinemachine) with an Orbital
# Follow + Cinemachine Deoccluder; the CinemachineBrain on the Camera blends automatically.
5. 画面揺れのフック(トリガーの管理はgame-feelが担当)
# Expose an additive offset the game-feel trauma model writes to; follow + shake compose.
var shake_offset := Vector2.ZERO                 # set each frame by game-feel (trauma^2 * noise)
func _apply(final_focus: Vector2) -> void:
    global_position = final_focus + shake_offset  # shake rides ON TOP of smooth follow
# Unity Cinemachine: add a CinemachineBasicMultiChannelPerlin and set amplitude from trauma.

よくある落とし穴

  • フレームごとの lerp(pos, target, const) はフレームレートに依存します。30 FPS では浮遊感が強くなり、144 FPS では反応が鋭くなります。1 - exp(-rate*dt) または SmoothDamp を使ってください。
  • ターゲットが動く前に通常の更新処理で追従すると、1 フレーム分の遅延によるジッターが発生します。移動や物理演算の解決後に、LateUpdate で追従させてください。
  • 境界のクランプがないと、レベルの端を越えた先にカメラが黒い領域を映してしまいます。注視点をレベルの矩形内にクランプしてください(中心ではなくビューが内側に収まるよう、ビューポートの半サイズを考慮してください)。
  • 動きの激しいゲームでデッドゾーンがないと、わずかな動きのたびにカメラが揺れて、吐き気を催す原因になります。
  • 三人称視点/一人称視点でピッチをクランプしないと、カメラが真上を越えて反転します。ピッチを約 ±80° にクランプしてください。
  • 3D でカメラが壁を突き抜ける場合は、スプリングアーム/遮蔽レイを使ってカメラを手前に引き寄せてください。
  • テレポート/リスポーン時の急な切り替わりは唐突です。意図的にハードカットする(その場合は平滑化をリセットする)か、素早くイーズインさせてください。SmoothDamp の距離が大きすぎて、カメラがレベルを横切ることのないようにしてください。
  • 加算オフセットではなく、シェイクで追従ターゲットを動かすと、追従処理とシェイクが互いに干渉します。追従を先に平滑化し、最後にシェイクオフセットを加えるように合成してください。
  • 軸ごとのデッドゾーンと半径ベースのデッドゾーンの混同に注意してください。矩形のデッドゾーンと円形のデッドゾーンでは感触が異なるため、意図的に選んでください。

参考資料

  • 指数平滑化/スプリングの導出、デッドゾーン+先読み+境界を備えた完全な 2D カメラリグ、3D スプリングアーム/オービットの詳細、一人称視点の視点操作、複数ターゲット/グループのフレーミングと分割画面、シネマティックカメラのブレンド、Cinemachine 3 / Godot Camera2D / PhantomCamera の対応関係については、references/follow-and-framing.md を参照してください。

関連スキル

  • game-feel — 画面シェイクのトラウマ/トリガーを担当します。このスキルは、そのスキルが書き込むオフセットを利用します。
  • godot-2d-movement、godot-3d-essentials — カメラがフレーミングするプレイヤー/ワールドと、Camera3D の設定を担当します。
  • physics-tuning — ジッターをなくすため、物理演算のステップに合わせてカメラの追従を補間します。
  • platformer、fps-shooter — このスキルがカメラのルールを実装するジャンルです。
  • performance-optimization — カメラの追加、レンダーターゲット、分割画面にかかるコストを扱います。

コメント