Skip to main content

Crate spine_bevy

Crate spine_bevy 

Source
Expand description

Bevy 0.19 plugin for spine_runtime: load, animate and draw Spine 4.3 skeletons.

Add SpinePlugin, load a .skel or .json export as a SpineSkeletonAsset, and spawn a SpineSkeleton with it. The plugin builds the runtime state once the asset loads, advances it every frame, and draws it as child mesh entities.

§Quick start (2D)

use bevy::prelude::*;
use spine_bevy::{SpinePlugin, SpineSkeleton, SpineSkeletonAsset, SpineSkeletonLoaderSettings};

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2d);
    let skel: Handle<SpineSkeletonAsset> = asset_server
        .load_builder()
        .with_settings(|s: &mut SpineSkeletonLoaderSettings| {
            s.atlas_path = Some("spineboy/export/spineboy-pma.atlas".into());
        })
        .load("spineboy/export/spineboy-pro.skel");
    commands.spawn(SpineSkeleton::new(skel).with_initial_animation(0, "walk", true));
}

App::new()
    .add_plugins(DefaultPlugins)
    .add_plugins(SpinePlugin)
    .add_systems(Startup, setup)
    .run();

§Quick start (3D)

Spawn a SpineRender3d marker alongside the SpineSkeleton and use a Camera3d. The rig is laid out in the entity’s local XY plane (z = 0), y-up and facing +Z, so it stands upright with an identity rotation. Spine units are usually pixels; scale the Transform down to scene units. See examples/spineboy_walk_3d.rs.

§Controlling playback

SpineSkeleton::play, SpineSkeleton::set_skin, and the time_scale, paused and physics fields cover the common cases. Calls made before the asset loads are queued. For queueing, mixing and track entries, use SpineSkeleton::animation_state_mut; for bones and slots, SpineSkeleton::skeleton_mut. Both return None until the asset loads.

Animation events arrive as messages. SpineKeyframeEvent carries keyframe events only; SpineStateEvent carries those plus track-entry lifecycle events (start, interrupt, end, complete, dispose).

use bevy::prelude::*;
use spine_bevy::{SpineKeyframeEvent, SpineSkeleton};

fn log_events(mut events: MessageReader<SpineKeyframeEvent>, skeletons: Query<&SpineSkeleton>) {
    for ev in events.read() {
        let Some(skeleton) = skeletons.get(ev.entity).ok().and_then(|s| s.skeleton()) else {
            continue;
        };
        let name = &skeleton.data().events[ev.event.data.index()].name;
        info!("{name} at {}s", ev.event.time);
    }
}

§How it fits together

SpinePlugin registers the asset loaders, the SpineMaterial (Material2d) and SpineMaterial3d (Material) plugins, the two event messages, and five chained system sets in Update:

  1. SpineSet::EnsureMarkers: inserts SpineRender2d on skeletons that carry no render-mode marker.
  2. SpineSet::Init: builds runtime state for skeletons whose asset has loaded.
  3. SpineSet::Tick: advances and applies animations, updates world transforms, and renders each skeleton’s RenderCommand list. Runs in parallel over skeletons.
  4. SpineSet::BuildMeshes: writes those commands into child mesh entities with a SpineMaterial or SpineMaterial3d, depending on the render-mode marker.
  5. SpineSet::Events: forwards lifecycle and keyframe events as SpineStateEvent and SpineKeyframeEvent messages.

Systems ordered .before(SpineSet::Tick) can change time_scale or queue animations and see the result the same frame. Systems that read bone positions should run .after(SpineSet::Tick).

§Atlas expectations

The materials assume premultiplied-alpha textures. Spine exports usually include a *-pma.atlas / *-pma.png pair beside the straight-alpha one. The loaders derive spineboy.atlas from spineboy-pro.skel, which in Spine’s examples is the straight-alpha atlas; set SpineSkeletonLoaderSettings::atlas_path to the PMA variant.

Re-exports§

pub use asset::SpineAtlasAsset;
pub use asset::SpineAtlasLoader;
pub use asset::SpineAtlasLoaderError;
pub use asset::SpineSkeletonAsset;
pub use asset::SpineSkeletonJsonLoader;
pub use asset::SpineSkeletonJsonLoaderError;
pub use asset::SpineSkeletonJsonLoaderSettings;
pub use asset::SpineSkeletonLoader;
pub use asset::SpineSkeletonLoaderError;
pub use asset::SpineSkeletonLoaderSettings;
pub use components::PendingAnimation;
pub use components::SpineRender2d;
pub use components::SpineRender3d;
pub use components::SpineSkeleton;
pub use components::SpineSkeletonState;
pub use material::SpineBlendMode;
pub use material::SpineColors;
pub use material::SpineMaterial;
pub use material::SpineMaterial3d;
pub use material::SpineMaterialKey;
pub use mesh::build_spine_meshes;
pub use mesh::build_spine_meshes_3d;
pub use systems::SpineInitialized;
pub use systems::SpineKeyframeEvent;
pub use systems::SpineSet;
pub use systems::SpineStateEvent;
pub use systems::drain_spine_events;
pub use systems::ensure_spine_render_marker;
pub use systems::initialize_spine_skeletons;
pub use systems::tick_spine_skeletons;

Modules§

asset
Asset types and loaders for Spine .atlas, .skel and .json files.
components
The SpineSkeleton component, its runtime state, and the render-mode markers.
material
The materials that draw Spine render commands: SpineMaterial for 2D, SpineMaterial3d for 3D. Both apply Spine’s two-color tint to a premultiplied-alpha atlas page and pick a pipeline per SpineBlendMode.
mesh
Turns each skeleton’s render commands into child mesh entities.
systems
The plugin’s systems, their SpineSets, and the event messages. SpinePlugin schedules all of them; they are public for apps that order their own systems against them.

Structs§

SpinePlugin
Registers Spine assets, loaders, materials, messages and systems. Add once, then spawn SpineSkeleton components.