Building a musical keyboard
Now that we have looked at how quickly we can create a simple empty script, let's explore the possibilities of scripting audio components. As we already saw in the last chapter, it is possible to use audio components without writing any scripts. However, scripting gives you more control over an audio source with only a few lines of code.
In this section, we are going to use scripting to build a simple keyboard that you will be able to play multiple instruments with. We will even allow the keyboard to record and play back sessions. All in less than 30 lines of code. Follow the instructions here, to start creating this script:
- We will continue where we left off from the last time by jumping back into MonoDevelop. Be sure the tab showing the Keyboard script is open and the script shell has not been modified.
- At the top of the file, just below the Keyboard class definition, enter the following lines of code:
private AudioSource audioSource;
public int transpose = 0;
- Those couple of lines just store the objects audioSource and an integer variable called transpose. The keyword at the start of each line denotes whether the variable is public or private. A private variable is only accessible within the class, while a public variable is visible outside the class and exposed in the editor interface. There is a way to expose private variables in the editor interface but we will leave that for another time.
- Next, enter the following line inside the Start method:
audioSource = GetComponent<AudioSource>();
- That line just finds an AudioSource component attached to the GameObject and stores the value in that private variable we declared earlier. GetComponent is a special method that searches the GameObject that the script is attached to and looks for a specific component denoted within <> tags. If there is no matching component, the method will return nothing or null.
- Pay attention when you are entering the next section of code in the Update method, as it is the longest piece of code you will need to enter:
var note = -1; // invalid value to detect when note is pressed
if (Input.GetKeyDown ("a")) note = 0; // C
if (Input.GetKeyDown ("s")) note = 2; // D
if (Input.GetKeyDown ("d")) note = 4; // E
if (Input.GetKeyDown ("f")) note = 5; // F
if (Input.GetKeyDown ("g")) note = 7; // G
if (Input.GetKeyDown ("h")) note = 9; // A
if (Input.GetKeyDown ("j")) note = 11; // B
if (Input.GetKeyDown ("k")) note = 12; // C
if (Input.GetKeyDown ("l")) note = 14; // D
if (note >= 0 && audioSource != null)
{ // if some key pressed...
audioSource.pitch = Mathf.Pow(2, (note+transpose) / 12.0f);
audioSource.Play();
}
- This section of code within the Update method is run every frame of the game. Generally, our game will run from 30-60 frames per second, which put another way, means that the section of code will run 30-60 times per second or more. The first line creates a variable with the var keyword called note and sets the value to -1. After that, it does several if tests to determine what the currently typed keyboard key is using a special object called Input. Input.GetKeyDown("") returns true or false depending on whether the key is pressed. If the key is pressed (true) the value for note is set depending on the key pressed. note is set to a value that matches the pitch of the key, you can see in the end of line comments which key matches which note. The last test or if statement is a test to see if the value for note is greater than or equal to zero and (represented with &&) the audioSource is not equal to null. In order for the script to execute the code inside the if statement, both conditions must be true, hence the use of the and (&&). Finally, if a key is pressed and our audioSource has been found, we set the pitch using some math, based on the key pressed (audioSource.pitch =). Then, we play the sound by calling the Play method on the audio source using audioSource.Play().
- After you are done entering all the code in the editor, your script should match what is shown in the screenshot here:
- Now that we have our script written from the menu, select File | Save to save the script. After the file is saved, return it to the Unity editor and wait while the script compiles, which should only take a few seconds. At this point, you will want to open the Console window and make sure no red compiler errors appear. An example of a compiler error is shown in the following screenshot:
- Unity is generally very helpful in locating the script error, showing the line and position. However, you can also double-click on the error in the Console window and your code editor will open automatically with the cursor set on the offending line.
- Be sure that your script is clean of any errors, you may see some warnings (yellow yield sign), but just ignore those and then click on the play button. The scene will run empty; this is because we have yet to set or even import our instrumental notes.
Well, hopefully you managed to get that script entered without any compiler errors. If you entered the script without any errors, give yourself a pat on the back. For those of you that had a few errors, don't get frustrated, it happens to the best of us.
If you feel that you just can't figure out this scripting thing and are completely stuck, not to worry. The completed version of the script is provided in the source code download folder called Scripts for this chapter.