---
# System prepended metadata

title: mk-microproject-simple-playable-piano

---

# mk-microproject-simple-playable-piano

in Unity

- may as well begin with the whole thing (but generated?)
- slide view slide to side
- maybe some other sliders for effects
- a "release the balls" (or rocks or other?) button to randomize play
- grey out (or semi-transparency) for keys not in a key as a feature?



## goals

- model the keys, add materials
- script to generate keyboard, looping through keys
- now play a sound on key press
- then play a sound on midi key press
- then move 3d key on key press
- then add sliders for filters
- record player input



## steps

### start the project

- begin with 3D core
- add empty for the basic set and put a plane in there
- add empty for the keyboard and add a script to it called `KeyboardGenerator`

### create the key prefabs

- add a cube
- add a white material to cube
- change cube to be key-sized `1.0`, `0.1` and `4.0`, say
- drag into prefabs folder
- add another cube and this time give it a `BlackKey` material; make it smaller and drag into prefabs too

### create an octave manually

- create an empty called octave
- drag in 7 white keys and 5 black keys
- arrange them on the x and y to be a keyboard
- drag that octave into prefabs

### generate an octave to start

- add an empty called octave
- instantiate a single key

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateOctave : MonoBehaviour
{
    public GameObject whiteKey;
    public GameObject blackKey;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("adding an octave of keys");
        GameObject whiteKey1 = Instantiate(whiteKey, new Vector3(0f, 1.0f, 0f), Quaternion.identity);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

```

and now use a loop to instantiate many

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateOctave : MonoBehaviour
{
    public GameObject whiteKey;
    public GameObject blackKey;
    public GameObject keyboardPosition; 

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("adding an octave of keys");
        //GameObject whiteKey1 = Instantiate(whiteKey, new Vector3(0f, 1.0f, 0f), Quaternion.identity);
        CreateOctave();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void CreateOctave()
    {
        for (int i = 0; i < 12; i++)
        {
            float position = i;
            GameObject KeyClone = Instantiate(whiteKey, new Vector3(i*1.1f + keyboardPosition.transform.position.x, keyboardPosition.transform.position.y, keyboardPosition.transform.position.z), keyboardPosition.transform.rotation);
        }
    }
}
```

or

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KeyboardController : MonoBehaviour
{

    public GameObject whiteKey, blackKey;
    // Start is called before the first frame update
    void Start()
    {
        for (int i = 0; i < 24; i++)
        {
            createKey(24*i, whiteKey, new Vector3(i*1.1f, 0, 0));
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private GameObject createKey(int midiKeyNumber, GameObject keyType, Vector3 location)
    {
        GameObject thisKey = Instantiate(keyType, location, Quaternion.identity);
        return thisKey;
    }
}

```


need to loop through the 12 notes and know when they're black and when white---and maybe we need to add to an index


- note 1, for instance
    - type: white
    - loc: 0
- note 2
    - type: black
    - loc: 0.5
- note 3
    - type: white
    - loc: 1
- note 4
    - type: black
    - loc: 1.5

how about

- node 1
    - initial white (midi index 0)
- node 2 = whole
    - black at position 1-.5 (midi index 1)
    - white at position 1 (midi index 2)
    - 
    - 

- next add execute in edit mode
- execute boolean (public) for executing
- reset boolean?
- 


```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]

public class KeyboardController : MonoBehaviour

{
    public GameObject whiteKey, blackKey;
    public bool buildKeyboard;
    public int numberOfOctaves;
    private GameObject keyboard;

    void Start()
    {
        
    }

    void Update()
    {
        if (buildKeyboard)
        {
            SetupScene();
            buildKeyboard = false;
        }
    }

    public void SetupScene()
    {
        if (keyboard != null)
        {
            DestroyImmediate(keyboard);
        }
        keyboard = new GameObject("Keyboard");
        float keyPosition = 0;
        for (int i = 0; i < 12*numberOfOctaves; i++)
        {
            GameObject theKey = createKey(i + 24, whiteKey, new Vector3(keyPosition, 0, 0));
            theKey.transform.parent = keyboard.transform;
            theKey.name = string.Format("Key: {0}", i+24);
            keyPosition += 1.1f;
        }
    }

    private GameObject createKey(int midiKeyNumber, GameObject keyType, Vector3 location)
    {
        GameObject thisKey = Instantiate(keyType, location, Quaternion.identity);
        return thisKey;
    }
}
```


## reference

- this [tutorial on dynamic content](https://www.youtube.com/watch?v=elkTZq-4Htk) is key
- 