Sync music and gaming events at Unity

                           Sync music and gaming events at Unity

                                        Sync music and gaming events at Unity

If you've ever played games like Guitar Hero, Osu or Bit Trip Runner you can feel how integral music is to the game play experience from the simple relationship of the player almost being in control of  music playing. It is surprising that for many games, the player based music doesn’t really add any meaningful experience to the game. In addition, such synchronization can be useful for creating special effects, but nevertheless almost never occurs except in the above mentioned rhythm games . So I decided to use this technique in your own game, and share operating time.

I have tried to describe the design, convenient for programming a large number of gaming events and running as soon as possible  in an optimal way. Which can be applied in almost any game, and perhaps it is useful to you if you are involved in developing them.

So, first you need to define a class-event:

public class Game_event {
    public char key; // Depending on the key will occur or that event
    public float time; // Since the start of the event
    [NonSerialized]public float finish_time; // Requires that the event was not created again after completion

    public bool isFinish(){
        //The function of checking the completion of the event
        return false;

    public void Create(){
        // Creates the need for an event object 
        // It is important that all the movements of objects depended on (Main.sound_time - time)

    public void Destroy(){
        // delete them

    public Game_event (float time, char key){
        this.time = time;
        this.key = key;


Further, the required class inherited from MonoBehaviour, which is the basic code and, of course, a link to an audio object. In my case it is a class Main.

public static float sound_time=0; 	// global variable in which to store the current time to play sound
public static List<Game_event> game_event = new List<Game_event>(); // list of events
void Update () {
    sound_time = sound.time;
    //sound - object type AudioSource, comprising playing music
    foreach (Game_event e in game_event) {
        if (sound_time>=e._time && sound_time<e.finish_time && !
   = true;
            e.finish_time = float.MaxValue;
            current_event =e;
        if (
            if (e.isFinish()) 	// function isFinish function can be resource-intensive, because the activity is checked before the event            {
                e.finish_time = sound_time;

There are several ways to create a variety of events: by transferring directly in code Game_event, create additional classes, or the use of a scripting language like Lua, which of course  is more convenient.

The most convenient way to edit, in my opinion, the binding of certain events to the keys, then the level of creation is transformed into "playing the piano", where your task is just to press the keys in rhythm with the music. That is why a key uses the appropriate symbols.

To realize the need to determine the available input keys:

public static char[] keys_s = {	'Q','W','E','R','T',

// And add the following code
void Update () {

    Event c_e = Event.current;
    if (c_e.isKey && c_e.type == EventType.KeyDown) {
        if (Array.Exists(Main.keys_s, c=>c==c_e.keyCode.ToString()[0])) // Check whether there is a pressed key in the array of permissible
            game_event.Add (new Game_event (sound_time,c_e.keyCode.ToString()[0]));

Now when you press the button, the list will be written to the corresponding event, which will be played in synchronou  sound.
This can be very useful to adjust the event under the figure of a sound wave. Get the texture with the image in the following way:

float[] samples = new float[sound.clip.samples * sound.clip.channels];
sound.clip.GetData(samples, 0); // Gets an array with the data sample on which to build texture
int frequency = sound.clip.frequency; // the bit rate of the sample
int scale = 10; // pixels per sample 1c

SoundTex = new Texture2D ((int)(sound.clip.length*sound.clip.channels*scale), 200);
int height = (int)(SoundTex.height / 2);
for (int i=0; i<SoundTex.width; i++) {
    int c_hi = 0;
    int c_low = 0;
    float s_hi = 0;
    float s_low = 0;

    // Calculate the average lower and upper secondary importance to 1px texture
    for (int k=0; k<(int)(frequency/scale); k++) {
        if (samples[k+i*(int)(frequency/scale)]>=0) {
        else {

// Draw a line from the middle of the lower to upper secondary
    // Post it on the lighter and darker inner upper part, solely for beauty    for (int j=0; j<(int)(SoundTex.height); j++) {
        if (j<(int)((s_hi/c_hi)*height*0.6f+height) && 
                SoundTex.SetPixel(i,j,new Color(0.7f,1,0.7f));
        if (j<=(int)((s_hi/c_hi)*height+height) && 
                SoundTex.SetPixel(i,j,new Color(0,1,0));
        else  	SoundTex.SetPixel(i,j,new Color(0,0,0,0));

SoundTex.Apply (); // Apply changes to the texture
// The result can be seen in the main picture


What it looks like in the editor, you can view a short video.

All data posted on the site represents accessible information that can be browsed and downloaded for free from the web.



User replies

No replies yet