void Start()
    {
        laser      = GetComponent <LaserBehaviour>();
        sequencer  = GameObject.FindGameObjectWithTag("Sequencer").GetComponent <TrackSequencer>();
        judger     = GetComponent <LaserMIDITimingJudge>();
        visualizer = GetComponentInChildren <LaserNoteVisualier>();

        rumble = GetComponent <ControllerRumble>();

        model             = this.transform.Find("Model").gameObject;
        modelInitialScale = model.transform.localScale;
    }
    private void BuildTracks()
    {
        // Remove old meshes

        List <GameObject> oldMeshes = new List <GameObject>();

        for (int i = 0; i < this.transform.childCount; i++)
        {
            oldMeshes.Add(this.transform.GetChild(i).gameObject);
        }

        foreach (GameObject obj in oldMeshes)
        {
            DestroyImmediate(obj);
        }

        // No laser harp to extrapolate tracks from
        if (laserHarp == null)
        {
            return;
        }

        int noteTracks = 0;

        accuracies = new Dictionary <GameObject, List <float> >();

        accuracyIndices = new Dictionary <int, GameObject>();

        foreach (LaserBehaviour laser in laserHarp.GetComponentsInChildren <LaserBehaviour>())
        {
            LaserMIDITimingJudge judger = laser.gameObject.GetComponent <LaserMIDITimingJudge>();

            // Make sure it is assigned notes
            judger.Initialize();

            List <float> trackAccuracies = new List <float>();

            for (int i = 0; i < judger.notes.Length; i++)
            {
                trackAccuracies.Add(0f);
            }

            accuracyIndices.Add(accuracies.Count, laser.gameObject);

            accuracies.Add(laser.gameObject, trackAccuracies);

            noteTracks++;
        }

        tracksVertices = new List <List <int> > [noteTracks + 1];

        tracks = new GameObject[noteTracks + 1];

        // The graph scale is added as a track to make it move with the others
        tracks[0]         = new GameObject("Graph Scale");
        tracksVertices[0] = new List <List <int> >();

        for (int i = 1; i < tracks.Length; i++)
        {
            tracks[i] = new GameObject("Track " + i);

            tracksVertices[i] = new List <List <int> >();
        }

        float zPos = -((trackWidth + trackSpacing) * tracks.Length) / 2 + trackSpacing / 2;

        float finalAvgAcc = 0;

        for (int i = 0; i < tracks.Length; i++)
        {
            GameObject track = tracks[i];

            List <List <int> > trackVertices = tracksVertices[i];

            track.transform.parent   = this.transform;
            track.transform.rotation = this.transform.rotation;

            track.transform.localPosition = new Vector3(0, 0, zPos);

            zPos += trackWidth + trackSpacing;

            MeshFilter   mesh     = track.AddComponent <MeshFilter>();
            MeshRenderer renderer = track.AddComponent <MeshRenderer>();

            // Copy values to each individual mesh
            renderer.sharedMaterial = GetComponent <MeshRenderer>().sharedMaterial;

            // Use second material for the graph scale to differentiate it from the others
            if (track == tracks[0] && GetComponent <MeshRenderer>().sharedMaterials.Length > 1)
            {
                renderer.sharedMaterial = GetComponent <MeshRenderer>().sharedMaterials[1];

                trackVertices.Add(new List <int>());
                trackVertices.Add(new List <int>());

                BuildMesh(track, new float[] { 1f, 1f }, trackVertices);
            }
            else
            {
                float[] trackAccuracies = GetTrackAccuracies(i);

                for (int i2 = 0; i2 < trackAccuracies.Length; i2++)
                {
                    trackVertices.Add(new List <int>());
                }

                finalAvgAcc += trackAccuracies[trackAccuracies.Length - 1];

                BuildMesh(track, trackAccuracies, trackVertices);
            }
        }

        //BuildGraphAxis(tracks[0], zPos);

        float graphCenterZ = -((trackWidth + trackSpacing) * tracks.Length) / 2 + trackSpacing / 2 + trackWidth + ((trackWidth + trackSpacing) * (tracks.Length - 1)) / 2;

        finalAvgAcc /= tracks.Length - 1;

        BuildGUI(finalAvgAcc, graphCenterZ);
    }