Hey guys! So today I went through the process of shrinking the massive 100+ of hard-coding for the musical electricity to ~30 lines of code. So just to illustrate why this was necessary, below is a screenshot of the hard-code (which ended up being multiple screenshots edited together because monodevelop couldn't zoom out enough).

This was just one function. I also had a second function which was near-identical except with alternating true/false statements. Now I know people will ask, "Why hard-code it in the first place?". The answer to that is simple in principle. I wasn't confident in what kind of variables I would need for this to work, nor the setup of the these variables. After I had hard-coded the formula, I gained a greater understanding of how it would work.
So to break it down the variables I knew were: the BPM (beats per minute), how many bars of music there were, how many notes and rests there were, how long each of them played for and the order in which they need to be played. To list these initially I used an integer array for noteLength, and integer array for silenceLength, a string array for noteOrSilence and an int for BPM. Things I still needed to find were the BPS (beats per second), how much time had passed since the song started and when to trigger the lightning/electricity.
To find the BPS I experimented with the Time function in Unity and ended with the equation: BPS = BPM / (60 * Time.timeScale). I chose this because I knew there were 60 BPS in the BPM but because of frame rates, I needed to multiply that by the timeScale. Finding how much time had passed since the track had started was the easiest with just creating a timer. Outside of the functions I declared a float "timer", then in start I set the timer to equal 0. Then when the function starting the lightning was called, it would start the equation "timer += 1 * Time.deltaTime" which would record how long it had been since the song started.
Triggering the electricity/lightning was the hardest part in hard-coding this. The method I chose originally was for every note in sequence:
if (timer == (noteLength or silenceLength)/BPS + total of previous noteLengths & silenceLengths / BPS){
lightning.enabled = true;
}
Then on the alternating note, I set the lightning to false. The problem with this is that there is no guarantee that the timer is going to exactly equal the note/silenceLength. It also raised issues with being able to tell when I needed to turn all lightnings off on the silences. This I ignored for now and fixed later when I shrunk the code because I actually knew manually when the rests in the music were. Next I chose to do this:
if (timer > (noteLength or silenceLength)/BPS + total-of-previous-noteLengths-&-silenceLengths / BPS && timer < this-note-length/BPS + the-next-note-length/BPS + total-of-previous-noteLengths-&-silenceLengths / BPS){
lightning.enabled = true;
}
Now already you can tell how the code got so long when I was individually writing each of the notes out and the previous notes twice.
But this did work as seen in the previous blog "Musical Electricity" or in the gif below.

Issues that were raised with hard-coding was the inefficiency of writing every single note out, the inefficiency of using strings to determine whether or not to start the lightning, the fact that I separated the rests and the notes made it difficult to just got noteLength [a] + noteLength [a+1] when I needed to add silenceLenth [a] too and the fact I didn't need to know how many bars the music was long. Another problem was figuring out how long the lightning should run, if each Tesla Coil was randomized.
The first thing I did when shrinking was to create a new near-identical script and get rid of the silenceLength and just add the rest into the noteLength array. Secondly, I change the NoteOrSilence string array to an array of bools where true means note and false mean rest. I also deleted the bars integer because I didn't need it. In the new script, I created an IEnumerator function instead of a void function because IEnumerator functions can use "Waitforseconds". I went on to create a for loop which looks like this:

Which you can probably tell is significantly smaller block of code then the previous hard-code version. The reason that in Update demoSong.playingTrack is false is because when that boolean is false on that script, the music plays. The boolean was poorly named admittedly. Now the music plays like this:

Or this:

Or this:

Which are all playing the same track. I have noticed though that the Random.Range doesn't always include the first or last numbers in the range which is unfortunate, but something I'll be working on later.
Let me know if you have any questions!