DISCLAIMER: I AM NOT A PROFESSIONAL PROGRAMMER
Methods of synchronizing game events to music
We used two methods (actually, a combination of the two) for most of our prototypes.
1. Straight up just keeping track of time (in FMOD or Unity)
This is the most straightforward way of programming a rhythm game in Unity, and fizzd’s (developer of Rhythm Doctor) tutorial is a great starting point that we used way back when we were developing Beat’Em for BVW festival. We won’t reiterate what’s in the link because it’s already a brilliantly-written tutorial.
Pros:
- Easy to get started! You can make a rhythm game right now!
- Can accommodate any typical beatmap- or song-based rhythm game
Cons:
- Doesn’t easily deal with dynamic BPM changes
- Unless you have some kind of external data structure that tells you when bpm changes happen
- Need to write your own events for beat-responsive objects
- We experienced issues in Unity when switching between tracks — it was hard to debug where and when lag was being introduced that threw our beat-tracking system off
Use when:
- Making a typical rhythm game, like a Guitar Hero clone
2. Use beat/marker events
This is a technique that requires some knowledge of middleware, in this case, FMOD. Based on tutorial by Alessandro Famà, we created our beat system script for FMOD integration. It utilizes the FMOD event callbacks for when beats and markers are encountered.
By assigning this beat system script to each ‘track’, we then can subscribe to OnBeat/OnMarker event and ‘listen’ to particular cues as beats or markers in different tracks (event) from any other script in the project. It also allows us to access Timeline information (can be extended by modifying ‘TimelineInfo’ class) from FMOD like bpm, timelinePosition, markerPosition as public attributes.
Pros:
- Precise way of keeping track of beats
- Very easy to start spawning things to the beat
- Easy workflow if your beatmapper is also your composer
- No need for an external data structure to store beatmaps
Cons:
- You still have to use techniques from (1), especially when trying to incorporate look-ahead
- If you want to pre-load your beatmap for some reason (e.g. filling the pipes in Chopin Beets) you still need some kind of data structure for the beatmap
- For offset: play a silent version of the track with markers before the actual track, use the offset markers to spawn things
- Markers are just strings — pretty limiting if you have a wide variety of cues or cue positions, or if cues need to store a bunch of data (e.g. Kinectic’s linked cues)
- There’s more work/space for your sound designer/engineer who will work in FMOD to create events with correct timeline information. (It can be a pro if you have a great sound designer like we do!)
Use when:
- Making a beat-responsive world game that doesn’t require players to perform beat-constrained actions
A combination of both methods is what we used most of the time. While it was very tempting to start using method 2 exclusively once we got the system working, the fact of the matter is that rhythm games always benefit from the implementation of some sort of look-ahead, and you can be more flexible with your look-ahead if you don’t solely base your game on beat events.
There are other methods too, e.g. parsing a MIDI file in Unity. We didn’t try this.