一键导入
bevy-cameras
Reference for cameras in Bevy — Camera2d, Camera3d, viewports, projection, render layers, mouse-to-world, and free camera controllers.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Reference for cameras in Bevy — Camera2d, Camera3d, viewports, projection, render layers, mouse-to-world, and free camera controllers.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Reference for Avian physics engine — rigid bodies, colliders, joints, spatial queries, collision events, character controllers, and debug rendering.
Reference for loading, managing, and tracking assets in Bevy — AssetServer, handles, loading states, events, custom loaders, and hot reloading.
Reference for playing and controlling audio in Bevy — AudioPlayer, AudioSink, spatial audio, volume, and playback settings.
Reference for Bevy Scene Notation (BSN) — the bsn! macro for defining inline scenes with components, children, relationships, observers, and dynamic props.
Reference for Bevy Commands — spawning/despawning entities, inserting/removing components, custom commands, trait extensions, and testing.
Reference for bevy_enhanced_input — observer-based input manager with actions, contexts, bindings, conditions, modifiers, presets, and mocking.
| name | bevy-cameras |
| description | Reference for cameras in Bevy — Camera2d, Camera3d, viewports, projection, render layers, mouse-to-world, and free camera controllers. |
| metadata | {"crate":"bevy_camera","bevy":"0.19"} |
commands.spawn(Camera2d);
commands.spawn(Camera3d);
Mark a main camera with a marker component for querying:
#[derive(Component)]
#[require(Camera2d)]
struct MainCamera;
Each Camera defines:
RenderTarget (Window, Image, TextureView, or None)Projection (orthographic for 2D, perspective for 3D)TransformMultiple cameras can render to the same window via viewports (split-screen, minimap):
commands.spawn((Camera2d, Camera { viewport: Some(Viewport { .. }), ..default() }));
Right-handed: X→right, Y→up, Z→towards viewer. Default center is (0,0).
fn move_camera(time: Res<Time>, input: Res<ButtonInput<KeyCode>>, mut t: Single<&mut Transform, With<MainCamera>>) {
let mut dir = Vec3::ZERO;
if input.pressed(KeyCode::KeyW) { dir.y += 1.; }
if input.pressed(KeyCode::KeyS) { dir.y -= 1.; }
if input.pressed(KeyCode::KeyA) { dir.x -= 1.; }
if input.pressed(KeyCode::KeyD) { dir.x += 1.; }
if dir != Vec3::ZERO { t.translation += dir.normalize() * time.delta_secs() * 500.; }
}
Zoom: modify Projection::Orthographic.scale.
fn move_3d(input: Res<ButtonInput<KeyCode>>, time: Res<Time>, mut t: Single<&mut Transform, With<MainCamera>>) {
let mut dir = Vec3::ZERO;
if input.pressed(KeyCode::KeyW) { dir += *t.forward(); }
if input.pressed(KeyCode::KeyS) { dir -= *t.forward(); }
if input.pressed(KeyCode::KeyA) { dir -= *t.right(); }
if input.pressed(KeyCode::KeyD) { dir += *t.right(); }
if dir != Vec3::ZERO { t.translation += dir.normalize() * time.delta_secs() * 10.; }
}
fn look(mut mm: MessageReader<MouseMotion>, mut t: Single<&mut Transform, With<Camera>>, time: Res<Time>) {
let dt = time.delta_secs();
let sensitivity = Vec2::new(0.12, 0.10);
for motion in mm.read() {
t.rotate_y(-motion.delta.x * dt * sensitivity.x);
let (yaw, pitch, roll) = t.rotation.to_euler(EulerRot::YXZ);
let pitch = (pitch - motion.delta.y * dt * sensitivity.y).clamp(-FRAC_PI_2 + 0.01, FRAC_PI_2 - 0.01);
t.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
}
}
Zoom (3D): modify Projection::Perspective.fov.
Enable free_camera feature. Then:
use bevy::camera_controller::free_camera::{FreeCamera, FreeCameraPlugin};
use bevy::camera::visibility::RenderLayers;
const BG: RenderLayers = RenderLayers::layer(1);
const FG: RenderLayers = RenderLayers::layer(2);
commands.spawn((FG, MainCamera)); // camera sees FG
commands.spawn((Player, FG)); // entity on FG
Cameras with higher Camera::order render later (on top). Use ClearColorConfig::None to not clear:
commands.spawn((Camera3d::default(), Camera { order: 1, clear_color: ClearColorConfig::None, ..default() }));
fn mouse_to_world(window: Single<&Window>, camera: Single<(&Camera, &GlobalTransform), With<MainCamera>>) {
let (cam, gt) = camera.into_inner();
if let Some(cursor) = window.cursor_position() {
if let Ok(ray) = cam.viewport_to_world(gt, cursor) {
let world = ray.origin.truncate();
// use world.x, world.y
}
}
}