add 2d_on_ui example (#18513)

hello ! im not english native, don't hesitate to correct my code
comments.

# Objective

a simple example for new users. This is a question asked a lot, and i
struggled to do it at first too.
see https://github.com/bevyengine/bevy/discussions/11223

## Showcase


![image](https://github.com/user-attachments/assets/179ec3ad-add5-4963-ab32-3ad1cc9df15c)

---------

Co-authored-by: theotherphil <phil.j.ellison@gmail.com>
This commit is contained in:
Lucas 2025-06-03 00:11:32 +02:00 committed by GitHub
parent 8255e6cda9
commit 05e0315355
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 81 additions and 0 deletions

View File

@ -3922,6 +3922,16 @@ description = "A simple 2D screen shake effect"
category = "Camera"
wasm = true
[[example]]
name = "2d_on_ui"
path = "examples/camera/2d_on_ui.rs"
doc-scrape-examples = true
[package.metadata.example.2d_on_ui]
name = "2D on Bevy UI"
description = "Shows how to render 2D objects on top of Bevy UI"
category = "Camera"
wasm = true
[package.metadata.example.fps_overlay]
name = "FPS overlay"

View File

@ -280,6 +280,7 @@ Example | Description
Example | Description
--- | ---
[2D on Bevy UI](../examples/camera/2d_on_ui.rs) | Shows how to render 2D objects on top of Bevy UI
[2D top-down camera](../examples/camera/2d_top_down_camera.rs) | A 2D top-down camera smoothly following player movements
[Camera Orbit](../examples/camera/camera_orbit.rs) | Shows how to orbit a static scene using pitch, yaw, and roll.
[Custom Projection](../examples/camera/custom_projection.rs) | Shows how to create custom camera projections.

View File

@ -0,0 +1,70 @@
//! This example shows how to render 2D objects on top of Bevy UI, by using a second camera with a higher `order` than the UI camera.
use bevy::{color::palettes::tailwind, prelude::*, render::view::RenderLayers};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, rotate_sprite)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// The default camera. `IsDefaultUiCamera` makes this the default camera to render UI elements to. Alternatively, you can add the `UiTargetCamera` component to root UI nodes to define which camera they should be rendered to.
commands.spawn((Camera2d, IsDefaultUiCamera));
// The second camera. The higher order means that this camera will be rendered after the first camera. We will render to this camera to draw on top of the UI.
commands.spawn((
Camera2d,
Camera {
order: 1,
// Don't draw anything in the background, to see the previous camera.
clear_color: ClearColorConfig::None,
..default()
},
// This camera will only render entities which are on the same render layer.
RenderLayers::layer(1),
));
commands.spawn((
// We could also use a `UiTargetCamera` component here instead of the general `IsDefaultUiCamera`.
Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
display: Display::Flex,
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
..default()
},
BackgroundColor(tailwind::ROSE_400.into()),
children![(
Node {
height: Val::Percent(30.),
width: Val::Percent(20.),
min_height: Val::Px(150.),
min_width: Val::Px(150.),
border: UiRect::all(Val::Px(2.)),
..default()
},
BorderRadius::all(Val::Percent(25.0)),
BorderColor::all(Color::WHITE),
)],
));
// This 2D object will be rendered on the second camera, on top of the default camera where the UI is rendered.
commands.spawn((
Sprite {
image: asset_server.load("textures/rpg/chars/sensei/sensei.png"),
custom_size: Some(Vec2::new(100., 100.)),
..default()
},
RenderLayers::layer(1),
));
}
fn rotate_sprite(time: Res<Time>, mut sprite: Single<&mut Transform, With<Sprite>>) {
// Use any of the regular 2D rendering features, for example rotating a sprite via its `Transform`.
sprite.rotation *=
Quat::from_rotation_z(time.delta_secs() * 0.5) * Quat::from_rotation_y(time.delta_secs());
}