Game Audio Development with Unity 5.X
上QQ阅读APP看书,第一时间看更新

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:

  1. 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.
  2. 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;
As you type within MonoDevelop, you will notice the editor helps you complete words by making suggestions. This feature is called intellisense and almost all code editors provide it at some level. To accept the top suggested word at any time just tap the Tab key.
  1. 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.
  2. Next, enter the following line inside the Start method:
audioSource = GetComponent<AudioSource>();
  1. 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.
Be sure that you always match the character case of any variable names or keywords. For instance, audioSource is completely different from AudioSource . You will also generally want to match the white space (spaces and new lines) in the code as well. While you can get away with omitting a lot of white space, it just makes the code more readable.
  1. 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();
}
  1. 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().
The math function expressed by Mathf.Pow(2, (note+transpose)/12.0f) is used to calculate the frequency or pitch of a note using the 12-tone equal temperament (TET) method or 12-TET. It is a way of tuning a musical instrument to match a 12 note octave scale, or in our case, a virtual musical instrument. This allows us to tune a single note of an instrument into a full virtual instrument. In Chapter 10, Composing Music, we use other methods to play and create virtual musical instruments.
  1. After you are done entering all the code in the editor, your script should match what is shown in the screenshot here:
Completed script in editor.
  1. 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:
Compiler errors shown in the Console window
 The compiler errors will often be the result of typos, incorrect case, or missing semicolons and/or braces. Try to take your time when entering a script for the first time in order to avoid these simple but frustrating mistakes.
  1. 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.
  2. 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.
If you are unable to play the scene, it likely means you have a script compilation error. Verify that the console window has no errors, and if you made any changes to the script, be sure they are saved.

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.