Rhythmic Animation

Sprite and UI animations syncing to the beat in Unity Engine

Bullet Dance is a rhythm game, so its animations must happen to the game's beat. While on the development team, I created a simple system to support this animation direction. The following Unity demo showcases various game objects, such as enemy characters and HUD, animating to the beat. As Wwise has yet to support WebGL, you will need to download the demo to play (currently only available on Windows):

In this demo, you can switch between game objects to see specific animations align with the rhythm. For the characters, you can preview animations in various directions, such as idle, walk, and—exclusive to the yokai hunter—attack. These animations are queued and will only play on the next fourth beat (strong beat). While the rhythm system compensates for the application's frame rate, visual latency may still occur. If you notice that animations are desyncing, you can adjust the latency offset at the bottom of the screen to keep animations on beat.

How does the animation stays on beat?

A MusicManager detects beats and dispatches an OnBeat event to all subscribed game components. One subset of these components is scripts derived from the RhythmAnimator class, which plays animations on the beat at which the event fired.

We standardized each animation file to 60 frames (1 second). The RhythmAnimator adjusts the animation speed based on the beat duration, speeding up or slowing down, so the animation stays synced regardless of the tempo.

Derived child classes of RhythmAnimator handle the animation logic for different game objects, such as the player or bosses. Animations can be called (plays immediately) or queued (plays on the next beat) by other game components, and the RhythmAnimator child manages the animation priority and ensures beat synchronization, even when the request is made off-beat.

Due to the project's structure, generic and specific scripts (i.e., generic health manager and boss-specific health manager) can request animations. To prevent errors when requesting animations outside of the RhythmAnimator base class, a local event system is used for each game object, handling animation requests safely.