chrisgliddon/bevy-skills

bevy-cameras

Use when spawning Bevy 0.19 Camera3d or Camera2d, choosing a Projection, rendering to an image with a RenderTarget component, wiring FreeCamera/PanCamera, building an obstruction-aware third-person orbit camera, ordering views, or setting per-camera Ambient…

View source

How to use

  1. Copy the installation command and review the source package before installing it in your own agent environment.
  2. Check the source document for required tools, credentials and supported hosts.
  3. Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/chrisgliddon/bevy-skills --skill bevy-cameras

Before you start

  • Installation does not include a model subscription, API allowance or permission to access your files.
  • Repository stars and installation counts describe activity, not an independent quality or security test.
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Bevy 0.19 — Cameras

When to use this skill

  • Spawning the main game camera.
  • Rendering to a texture (mini-map, portal, post-process target).
  • Wanting a drop-in free-look or pan controller without writing your own.
  • Configuring multiple cameras with different order for overlays.
  • Setting ambient brightness on a per-camera basis.
  • Building a third-person pivot/boom camera with fixed-pose interpolation and Rapier

obstruction casts.

Canonical pattern

FreeCamera/PanCamera are gated behind Cargo features. In Cargo.toml:

toml
bevy = { version = "0.19", features = ["free_camera", "pan_camera"] }
rust
use bevy::asset::RenderAssetUsages;
use bevy::camera::RenderTarget;
use bevy::camera_controller::free_camera::{FreeCamera, FreeCameraPlugin};
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(FreeCameraPlugin) // adds the input wiring
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
    // 1. Main camera with the built-in free-look controller.
    commands.spawn((
        Camera3d::default(),
        FreeCamera::default(),
        Transform::from_xyz(0.0, 4.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));

    // 2. A texture target for an off-screen render pass (mini-map, portal).
    let size = bevy::render::render_resource::Extent3d {
        width: 512,
        height: 512,
        depth_or_array_layers: 1,
    };
    let mut image = Image::new_fill(
        size,
        bevy::render::render_resource::TextureDimension::D2,
        &[0; 4],
        bevy::render::render_resource::TextureFormat::Bgra8UnormSrgb,
        RenderAssetUsages::default(),
    );
    image.texture_descriptor.usage =
        bevy::render::render_resource::TextureUsages::TEXTURE_BINDING
            | bevy::render::render_resource::TextureUsages::COPY_DST
            | bevy::render::render_resource::TextureUsages::RENDER_ATTACHMENT;
    let image_handle = images.add(image);

    // 3. A second camera that draws into the texture.
    //    RenderTarget is now a *separate* component, not Camera.target.
    commands.spawn((
        Camera3d::default(),
        Camera { order: -1, ..default() }, // -1 = render before the main camera
        RenderTarget::Image(image_handle.into()),
        Transform::from_xyz(10.0, 5.0, 0.0).looking_at(Vec3::ZERO, Vec3::Y),
    ));
}

Choosing a projection

rust
use bevy::prelude::*;
use bevy::camera::Projection;

# fn _proj(mut commands: Commands) {
// Default perspective (45° vertical FOV).
commands.spawn((Camera3d::default(), Projection::default()));

// Orthographic for top-down or strategy views.
commands.spawn((
    Camera3d::default(),
    Projection::Orthographic(OrthographicProjection {
        scale: 10.0,
        ..OrthographicProjection::default_3d()
    }),
));
# }

Ambient light: world default vs per-camera

rust
use bevy::prelude::*;
use bevy::light::GlobalAmbientLight;

# fn _amb(app: &mut App, mut commands: Commands) {
// World default — applies everywhere unless a camera overrides.
app.insert_resource(GlobalAmbientLight {
    brightness: 200.0,
    ..default()
});

// Per-camera override (`AmbientLight` is a Component).
commands.spawn((Camera3d::default(), AmbientLight { brightness: 1000.0, ..default() }));
# }

Bevy 0.19 gotchas

  • `RenderTarget` is a separate component. Camera { target: ... } is an old

shape. Spawn RenderTarget alongside Camera3d / Camera.

  • `AmbientLight` is no longer a `Resource`. It's a per-camera component. The world default lives in the GlobalAmbientLight resource.
  • `ImageRenderTarget::scale_factor` is `f32` (used to be wrapped in FloatOrd).
  • Camera `order` is signed. Lower values render first. Use order: -1 for off-screen passes you'll sample in the main pass.
  • `FreeCamera` / `PanCamera` need their plugin and Cargo feature. Add

features = ["free_camera", "pan_camera"]; spawning only the component does not install its input systems.

  • Imports: bevy::camera::RenderTarget, bevy::camera_controller::{free_camera::*, pan_camera::*}, bevy::light::GlobalAmbientLight. None are in the prelude.

See also

pitch limits, smoothing, fixed interpolation, sphere casts, hysteresis, and actor fade.

and render systems.

and correct mouse-delta transfer.

materials.

  • `bevy-a11y` — FOV, shake, motion, and viewport accessibility.
from this repository

More skills

All skills