# 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 -