Getting started with Bevy

This is a guide on how to get started with Indigauge for the Bevy engine (compatible with Bevy 0.18).

For more examples check out the examples in the repository or the bevy-mod-indigauge README.

Add the cargo lib

Add the package to your game project.

cargo add bevy-mod-indigauge

Or add it manually in Cargo.toml:

[dependencies]
bevy = "0.18"
bevy-mod-indigauge = { version = "0.6" }

Add the plugin to the app

NOTE

Have the public api key available from the previous step.

Minimal example

This example initializes the plugin and starts a new session when the game is opened. The only thing that will be sent in automatically is any crash-events.

main.rs
use bevy::prelude::*;
use bevy_mod_indigauge::prelude::*;

fn main() {
  App::new()
    .add_plugins(DefaultPlugins)
    .add_plugins(
      IndigaugePlugin::<EmptySessionMeta>::new(
        "YOUR_PUBLIC_KEY",
        "My game name",
        env!("CARGO_PKG_VERSION")
      )
      // Optional: Set mode (Defaults to live). Dev mode is useful for testing and debugging and does not send events to the server.
      .mode(IndigaugeMode::Dev)
      // Optional: Set preferred log-level (Defaults to Info)
      .log_level(IndigaugeLogLevel::Info)
    )
    .add_systems(Startup, setup)
    .run();
}

fn setup(mut commands: Commands) {
  commands.spawn((Camera2d, IsDefaultUiCamera));
  commands.trigger(StartSessionEvent::new());
}

Advanced example

This example does multiple things:

  • Initializes the plugin and starts a new session when the game is opened.
  • Every two seconds an event will be queued with a counter value.
  • Displays a feedback form if the user presses Space on their keyboard.
  • Sends in any crash events that may occur.
main.rs
use std::time::Duration;
use bevy::{prelude::*, time::common_conditions::on_timer};
use bevy_mod_indigauge::prelude::*;

struct EventType;

impl EventType {
  const COUNTER_INCREASE: &'static str = "counter.increase";
}

fn main() {
  App::new()
    .add_plugins(DefaultPlugins)
    .add_plugins(
      IndigaugePlugin::<EmptySessionMeta>::new(
        "YOUR_PUBLIC_KEY",
        "My game name",
        env!("CARGO_PKG_VERSION")
      )
      // Optional: Set mode (Defaults to live). Dev mode is useful for testing and debugging and does not send events to the server.
      .mode(IndigaugeMode::Dev)
      // Optional: Set preferred log-level (Defaults to Info)
      .log_level(IndigaugeLogLevel::Info)
    )
    // Optional: Customize the feedback panel styles
    .insert_resource(FeedbackPanelStyles {
      primary: Color::srgb_u8(147, 164, 255),
      primary_hover: Color::srgb_u8(124, 140, 250),
      secondary: Color::srgb_u8(147, 164, 255),
      secondary_hover: Color::srgb_u8(124, 140, 250),
      background: Color::srgb_u8(15, 23, 42),
      surface: Color::srgb_u8(30, 41, 59),
      border: Color::srgb_u8(51, 65, 85),
      text_primary: Color::srgb_u8(248, 250, 252),
      text_secondary: Color::srgb_u8(203, 213, 225),
      success: Color::srgb_u8(34, 197, 94),
      error: Color::srgb_u8(248, 113, 113),
      warning: Color::srgb_u8(250, 204, 21),
      accent: Color::srgb_u8(168, 85, 247),
    })
    .add_systems(Startup, setup)
    .add_systems(Update, (trigger_feedback_with_question, track_counter.run_if(on_timer(Duration::from_secs(2)))))
    .run();
}

fn setup(mut commands: Commands) {
  commands.spawn((Camera2d, IsDefaultUiCamera));
  commands.trigger(StartSessionEvent::new().with_platform("steam"));
}

fn trigger_feedback_with_question(
  mut commands: Commands,
  keys: Res<ButtonInput<KeyCode>>,
  existing: Option<Res<FeedbackPanelProps>>,
) {
  if existing.is_some() {
    return;
  }
  if keys.just_pressed(KeyCode::Space) {
    // This is how you manually trigger the feedback panel
    commands.insert_resource(
      FeedbackPanelProps::with_question("What did you think about level 3?", FeedbackCategory::Gameplay),
    );
  }
}

fn track_counter(mut counter: Local<u32>) {
  *counter += 1;
  ig_info!(EventType::COUNTER_INCREASE, { "value": *counter });
}

Tracing support

Enable the tracing feature to forward structured log events to Indigauge through Bevy's LogPlugin. This is useful for sending telemetry from existing tracing-based instrumentation.

Cargo.toml:

[dependencies]
bevy = { version = "0.18" }
bevy-mod-indigauge = { version = "0.6", features = ["tracing"] }

Usage example with the default tracing layer (forwards all events):

main.rs
use bevy::{log::{LogPlugin, BoxedLayer}, prelude::*, time::common_conditions::on_timer};
use bevy_mod_indigauge::{prelude::*, tracing::default_bevy_indigauge_layer};
use std::time::Duration;

pub fn default_indigauge_layer(_app: &mut App) -> Option<BoxedLayer> {
  Some(Box::new(default_bevy_indigauge_layer()))
}

fn main() {
  App::new()
    .add_plugins(DefaultPlugins.set(LogPlugin { custom_layer: default_indigauge_layer, ..default() }))
    .add_plugins(IndigaugePlugin::<EmptySessionMeta>::new("YOUR_PUBLIC_KEY", "My game name", env!("CARGO_PKG_VERSION")))
    .add_systems(Startup, setup)
    .run();
}

fn setup(mut commands: Commands) {
  commands.spawn((Camera2d, IsDefaultUiCamera));
  commands.trigger(StartSessionEvent::new());
}

You can also configure the layer with custom filters:

use bevy_mod_indigauge::tracing::{default_bevy_indigauge_layer, IndigaugeLogLevel};

pub fn custom_indigauge_layer(_app: &mut App) -> Option<BoxedLayer> {
  Some(Box::new(
    default_bevy_indigauge_layer()
      .with_event_type_required(true)
      .with_filters(vec!["bevy_mod_othercrate"])
      .with_levels(vec![
        IndigaugeLogLevel::Info,
        IndigaugeLogLevel::Warn,
        IndigaugeLogLevel::Error,
      ]),
  ))
}

Any tracing event with an ig field will be forwarded:

info!(ig = "counter.increase", value = counter_value);

The ig field must follow the same namespace.event rules as the ig_* macros (see the Event Naming guide).

Feature flags

  • feedback (enabled by default): provides the in-game feedback panel rendered with Bevy UI + picking.
  • feedback_egui (optional): renders the feedback panel using bevy_egui instead of Bevy UI (native only).
  • panic_handler (enabled by default): capture native panics/crashes as events.
  • tracing: enable tracing-layer integration.
# Default (Bevy UI panel, panic handler)
bevy-mod-indigauge = { version = "0.6" }

# Use bevy_egui for the feedback panel (native only)
bevy-mod-indigauge = { version = "0.6", features = ["feedback_egui"] }
WARNING

On WASM builds the panic handler is disabled. No crash reports will be sent as events to the Indigauge API.

If you need a minimal dependency set (for example for WASM builds), disable default features in Cargo.toml and opt-in to the features you need.

Bevy compatibility

Bevybevy-mod-indigauge
0.180.6
0.170.5
0.160.4
0.150.1 – 0.3