How to use
- Copy the installation command and review the source package before installing it in your own agent environment.
- Check the source document for required tools, credentials and supported hosts.
- Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/chrisgliddon/bevy-skills --skill bevy-camerasBefore 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.
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
orderfor 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:
bevy = { version = "0.19", features = ["free_camera", "pan_camera"] }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
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
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
GlobalAmbientLightresource. - `ImageRenderTarget::scale_factor` is `f32` (used to be wrapped in
FloatOrd). - Camera `order` is signed. Lower values render first. Use
order: -1for 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
- Third-person orbit camera — pivot/boom separation,
pitch limits, smoothing, fixed interpolation, sphere casts, hysteresis, and actor fade.
- `bevy-rendering` — renderer choice, forward/deferred,
and render systems.
- `bevy-input-actions` — rebindable camera/aim input
and correct mouse-delta transfer.
- `bevy-physics` — Rapier scene-query setup and filtering.
- `bevy-pbr-materials` — lighting and camera-visible
materials.
- `bevy-a11y` — FOV, shake, motion, and viewport accessibility.

